home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Experimental BBS Explossion 3
/
Experimental BBS Explossion III.iso
/
c
/
rxdoscmd.zip
/
RXDOSCMD.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-06-06
|
233KB
|
5,445 lines
TITLE 'Cmd - RxDOS Command Shell'
PAGE 59, 132
.LALL
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; RxDOS Command Shell ;
;...............................................................;
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Real Time Dos ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; This material was created as a published version of a DOS ;
; equivalent product. This program logically functions in ;
; the same way as MSDOS functions and it is internal data ;
; structure compliant with MSDOS 5.0 ;
; ;
; This product is distributed AS IS and contains no warranty ;
; whatsoever, including warranty of merchantability or ;
; fitness for a particular purpose. ;
; ;
; ;
; (c) Copyright 1990, 1992. Api Software and Mike Podanoffsky ;
; All Rights Reserved Worldwide. ;
; ;
; This product is protected under copyright laws and may not ;
; be reproduced in whole or in part, in any form or media, ;
; included but not limited to source listing, facimilie, data ;
; transmission, cd-rom, or floppy disk without the expressed ;
; written consent of the author. ;
; ;
; Licence for distribution in commercial use: ;
; ;
; Api Software ;
; 12 South Walker Street ;
; Lowell, MA 01851 ;
; 508/ 454-4961. ;
; ;
;...............................................................;
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; RxDOS Command Shell ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Programmer's Notes: ;
; ;
; Command Shell consists of two parts bound together into a ;
; single executable load. There exists a single resident ;
; command shell which is accessible by an Int 2Eh. ;
; ;
;...............................................................;
include rxdosmac.asm
include rxdosdef.asm
include rxdoscin.asm
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Execution Control ;
;...............................................................;
EXECCONTROL struc
exCtrlArgArray dd ?
exCtrlStdInHandle dw ?
exCtrlStdOutHandle dw ?
exCtrlFlags dw ?
exCtrlLoadExecBlock db sizeLOADEXEC dup(?)
EXECCONTROL ends
exCtrlPiped equ 8000h
exCtrlAppend equ 4000h ; append to stdout
sizeEXECCONTROL equ size EXECCONTROL
_BAT equ 0
_EXE equ 1
_COM equ 2
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; If Special Values ;
;...............................................................;
IF_NOT equ 01h
IF_ERRORLEVEL equ 02h
IF_EXIST equ 03h
_ARGTEXT equ _high
_ARGTYPE equ _low
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; RxDOS Command Shell ;
;...............................................................;
public CommandBegin
RxDOSCMD SEGMENT PUBLIC 'CODE'
assume cs:RxDOSCMD, ds:RxDOSCMD, es:RxDOSCMD, ss:RxDOSCMD
org 100h
public CheckOptOneArg
public CmndError_BadSwitch
public CmndError_CannotCopyUntoSelf
public CmndError_CannotCreateFile
public CmndError_ContentsLostBeforeCopy
public CmndError_FileAlreadyExists
public CmndError_FileNotFound
public CmndError_InvalidDate
public CmndError_InvalidDrive
public CmndError_InvalidTime
public CmndError_NoFilesFound
public CmndError_SyntaxError
public CRLF
public CmndLookup
public _Copy_FilesCopied
public CountArgs
public deleteArg
public deleteEnvVariable
public DisplayError
public DisplayErrorMessage
public DisplayLine
public insertEnvVariable
public PreProcessCmndLine
public ReplaceForVariables
public returnVolumeName
public searchEnvVariable
public setPagingMode
public RxDOSIntl_DateTemplate
public RxDOSIntl_DayOfWeek
public RxDOSIntl_TimeTemplate
public RxDOSIntl_DateTimeTable
public RxDOS_AllFiles
public RxDOS_DefaultPrompt
public RxDOS_DTA
public RxDOS_ForArgs
public RxDOS_Prompt
public RxDOS_PromptSpec
public RxDOS_Version
public _AppendPathName
public _CmndParse_Break
public _CopyString
public _DirAttribSwitch
public _DirBareSwitch
public _DirLowerCaseSwitch
public _DirOrderSwitch
public _DirPauseSwitch
public _DirSubDirSwitch
public _DirSwitches
public _DirWideSwitch
public _Dir_DirectoryOf
public _Dir_DirEntry
public _Dir_FileEntry
public _Dir_Files
public _Dir_NoVolumeLabel
public _Dir_VolumeLabel
public _Dir_VolumeSerialNumber
public _endofString
public _EnvSegment
public _GetNumber
public _getStdinLine
public _InternalCommandParser
public _lowerCase
public _lowerCaseString
public _PleaseEnterDate
public _PleaseEnterTime
public _ShowCurrentDate
public _ShowCurrentTime
public _sprintf
public _SwitchChar
; in rxdoscpy.asm
extrn _Copy : near
; in rxdosdir.asm
extrn _Dir : near
; in rxdosfor.asm
extrn _For : near
; in rxdosprm.asm
extrn _Prompt : near
extrn _Date : near
extrn _Time : near
extrn DisplayPrompt : near
extrn formatCurrentDate : near
extrn formatCurrentTime : near
; in rxdosren.asm
extrn _Rename : near
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; RxDOS Command Parser/ Execute ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ds:si command line beginning with a count ;
; (this fct does not rely on CR at end of buffer) ;
; ;
; The command is executed, which may require loading another ;
; program. ;
; ;
; ** MSDOS Difference ** ;
; ;
; Unlike MSDOS, this module will preserve all registers. ;
;...............................................................;
_InternalCommandParser proc far
Entry
def _commandLine, si ; argument is copied
defwords __argarray, 64 ; 64 arguments
; (last arg is null)
SaveAllRegisters ; save all registers
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; get switch character
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
setDS ss
setES ss
Int21 GetSetSwitchChar, 00 ; get switch char
mov byte ptr [ _SwitchChar ], dl ; save switch character
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; parse
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
getarg si, _commandLine
lea di, offset [ __argarray ][ bp ]
call _BuildArgArray ; break up into arg list
jz _intCommandParser_36 ; if no arguments -->
mov si, word ptr [ __argarray ][ bp ] ; get lead argument
cmp byte ptr [ si ], ':' ; label line ?
jz _intCommandParser_36 ; ignore -->
lea di, offset [ __argarray ][ bp ]
call _executeCommandArray
cmp byte ptr [ _EchoStatus ], false ; echo ?
jz _intCommandParser_36 ; if no echo -->
call CRLF
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; command completed
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_intCommandParser_36:
restoreAllRegisters
mov sp, bp
pop bp ; restore bp
ret
_InternalCommandParser endp
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; RxDOS Command Parser/ Execute ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ds:si command line beginning with a count ;
; (this fct does not rely on CR at end of buffer) ;
; ;
; The command is executed, which may require loading another ;
; program. ;
; ;
; ** MSDOS Difference ** ;
; ;
; Unlike MSDOS, this module will preserve all registers. ;
;...............................................................;
_CommandParser proc far
Entry
defbytes _commandLine, 128 ; argument is copied
; (last arg is null)
SaveAllRegisters ; save all registers
sti
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; copy command line
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
lodsb
mov cl, al ; length
xor ch, ch
or cx, cx
jz _commandParser_36 ; if no arguments -->
setES ss
lea di, offset [ _commandLine ][ bp ]
rep movsb ; copy command line
xor ax, ax
stosb ; add a null terminator
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; parse line
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
lea si, offset [ _commandLine ][ bp ]
call _InternalCommandParser
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; command completed
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_commandParser_36:
restoreAllRegisters
mov sp, bp
pop bp ; restore bp
iret
_CommandParser endp
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Execute Command Stored in Arg Array ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:di argument array ;
;...............................................................;
_executeCommandArray:
Entry
def __argarray, di ; argument array
defbytes __execCtrlBlock, sizeEXECCONTROL
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; scan remainder of command line for pipe, stdin and stdout args
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
xor ax, ax
lea bx, offset [ __execCtrlBlock ][ bp ]
push di
mov di, bx
mov cx, sizeEXECCONTROL
rep stosb ; clear exec control block
pop di
mov dx, -1
mov word ptr [ exCtrlStdOutHandle ][ bx ], dx ; no stdout file
mov word ptr [ exCtrlStdInHandle ][ bx ], dx ; no stdin file
_executeArray_04:
lea bx, offset [ __execCtrlBlock ][ bp ]
call _assignRedirectedDevices ; arg array in [di]
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; see if command is valid
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
mov si, word ptr [ di ] ; get lead argument
mov di, offset RxDOS_InternalCommands
call CmndLookup ; lookup command
jnc _executeArray_26 ; if command found -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; see if valid drive letter
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
mov di, word ptr [ __argarray ][ bp ] ; arguments pointer
mov si, word ptr [ di ] ; get lead argument
cmp word ptr ss:[ si+1 ], ':' ; disk select ?
jnz _executeArray_12 ; if unknown -->
call CountArgs ; count how many arguments
call _DiskSelect ; process disk select
jmp _executeArray_36
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; see if .exe, .com, or .bat
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_executeArray_12:
call _executeProgram ; try to execute program
jmp _executeArray_36
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; go process command
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_executeArray_26:
mov di, word ptr [ __argarray ][ bp ] ; arguments pointer
call SplitArgs ; for cd.. cases
inc di
inc di ; argument array past arg
mov si, word ptr [ di ] ; get lead argument
call CountArgs ; count how many arguments
call bx ; go execute commands
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; done
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_executeArray_36:
mov byte ptr [ PageLines ], 00 ; cancel page lines
mov bx, STDIN
mov ax, word ptr [ __execCtrlBlock. exCtrlStdInHandle ][ bp ]
call _CloseRedirectedDevice
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; is arg piped ?
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
getarg di, __argarray
test word ptr [ __execCtrlBlock. exCtrlFlags ][ bp ], exCtrlPiped
jnz _executeArray_38
mov bx, STDOUT
mov ax, word ptr [ __execCtrlBlock. exCtrlStdOutHandle ][ bp ]
call _CloseRedirectedDevice
Return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; arg is piped
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_executeArray_38:
mov ax, word ptr [ di ]
inc di
inc di
or ax, ax ; at end of search ?
jnz _executeArray_38 ; keep loopking -->
_executeArray_42:
and word ptr [ __execCtrlBlock. exCtrlFlags ][ bp ], NOT exCtrlPiped
storarg __argarray, di ; next in arg array
; must reopen file given by temp...
; maybe should not have closed it.
mov cx, STDOUT
call _assignGetCurrHandle ; get current handle
mov word ptr [ __execCtrlBlock. exCtrlStdInHandle ][ bp ], ax
mov bx, STDOUT
Int21 CommitFile ; close stdout
xor cx, cx
xor dx, dx
mov bx, STDOUT
Int21 MoveFilePointer, SEEK_BEG ; point to beg of file
mov bx, STDOUT
mov cx, STDIN
Int21 ForceFileHandle ; redirect stdout -> stdin
mov bx, STDOUT
mov ax, word ptr [ __execCtrlBlock. exCtrlStdOutHandle ][ bp ]
call _CloseRedirectedDevice
getarg di, __argarray ; next in arg array
jmp _executeArray_04
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Build Argument Array ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ds:si command line beginning with a count ;
; (this fct does not rely on CR at end of buffer) ;
; ss:di argument array ;
; (returns a pointer into the command line at the ;
; start of each argument. Multiple switches are ;
; detected by testing the get command switch char). ;
; ;
; Returns: ;
; zr if no arguments passed ;
;...............................................................;
_BuildArgArray:
Entry
ddef _commandLine, ds, si
ddef __argarray, ss, di ; 64 arguments
def _insideString, 0000 ; not inside string (yet)
setES ss
mov word ptr ss:[ di ], 0000 ; add null table terminator
mov word ptr ss:[ di+2 ], 0000 ; two nulls is complete end
xor cx, cx ; set record flag
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; scan argument
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_buildArgArray_08:
lodsb ; get character
or al, al ; end of line ?
jz _buildArgArray_36 ; yes, end of arg -->
cmp al, ' ' ; space ?
jz _buildArgArray_26 ; yes, end of arg -->
cmp al, byte ptr [ _SwitchChar ] ; switch character ?
jz _buildArgArray_14 ; yes, end of arg -->
call _CmndParse_Break ; parse break ?
jz _buildArgArray_18 ; yes, test and record -->
or cx, cx ; record flag ?
jnz _buildArgArray_08 ; no, scan -->
_buildArgArray_14:
mov ax, si
dec ax
stosw ; store pointer to argument
mov word ptr ss:[ di ], 0000 ; add null table terminator
mov word ptr ss:[ di+2 ], 0000 ; two nulls is complete end
mov cx, -1 ; no need to re-record
jmp _buildArgArray_08 ; go scan
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; special arg
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_buildArgArray_18:
cmp al, singleQuote
jz _buildArgArray_30
cmp al, doubleQuote
jz _buildArgArray_30
_buildArgArray_22:
cmp byte ptr [ _insideString ][ bp ], 00 ; inside string ?
jnz _buildArgArray_08 ; skip testing for the items below
mov ax, si
dec ax
stosw ; store pointer to argument
mov word ptr ss:[ di ], 0000 ; add null table terminator
mov word ptr ss:[ di+2 ], 0000 ; two nulls is complete end
_buildArgArray_26:
xor cx, cx ; set record flag
jmp _buildArgArray_08 ; scan start
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; set inside string mode
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_buildArgArray_30:
xor ah, ah
xchg ah, byte ptr [ _insideString ][ bp ] ; kill inside string mode
or ah, ah ; was inside string ?
jnz _buildArgArray_08 ; yes, continue parsing line -->
mov byte ptr [ _insideString ][ bp ], al ; else set inside string mode
mov ax, si
dec ax
stosw ; store pointer to argument
mov word ptr ss:[ di ], 0000 ; add null table terminator
mov word ptr ss:[ di+2 ], 0000 ; two nulls is complete end
mov cx, -1 ; no need to record again
jmp _buildArgArray_08 ; continue scanning -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_buildArgArray_36:
mov di, word ptr [ __argarray. _pointer ][ bp ]
cmp word ptr [ di ], 0000 ; args passed ?
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Split Args ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Some args are passed in the arg array as a single arg pointer;
; when in fact they need to be split up, as in 'cd..' ;
; ;
; This routine will fix that. ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; di pointer to args array ;
;...............................................................;
SplitArgs:
Entry
def __argarray, di ; pointer to args
mov si, word ptr [ di ] ; get arg
or si, si ; args passed ?
jz _SplitArgs_36 ; none -->
_SplitArgs_08:
lodsb
or al, al ; null ?
jz _SplitArgs_36 ; end of search -->
cmp al, ' '+1 ; space or other break ?
jc _SplitArgs_36 ; end of search -->
cmp al, '\' ; dir break ?
jz _SplitArgs_12 ; yes, insert arg -->
cmp al, '.' ; period break ?
jnz _SplitArgs_08 ; continue if none of the above -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Insert Arg
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_SplitArgs_12:
mov ax, si ; set arg
dec ax
_SplitArgs_16:
inc di
inc di
xchg ax, word ptr [ di ] ; push arg
or ax, ax ; end of table ?
jnz _SplitArgs_16 ; not yet -->
cmp word ptr [ di+2 ], 0000 ; 2nd null follows ?
jnz _SplitArgs_16 ; no, keep inserting -->
mov word ptr [ di+2 ], ax ; make sure we put two NULLS
mov word ptr [ di+4 ], ax ;
_SplitArgs_36:
getarg di, __argarray ; pointer to args
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Command Parse Break ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; al character from parser ;
; ;
; Returns: ;
; zr is a break character ;
;...............................................................;
_CmndParse_Break:
push si
mov si, offset _CmndParse_Separators
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; lookup
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_CmndParse_Break_08:
cmp byte ptr cs:[ si ], 0
jz _CmndParse_Break_12
cmp al, byte ptr cs:[ si ]
jz _CmndParse_Break_16
inc si
jmp _CmndParse_Break_08
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; exit
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_CmndParse_Break_12:
or al, al ; non-zero if end of table
_CmndParse_Break_16:
pop si
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Scan and Assign Redirection ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:di argument array ;
; ss:bx pointer to Execution Control Block ;
;...............................................................;
_assignRedirectedDevices:
Entry
def __argarray, di ; argument array
def __contargarray, di ; continue argument array
def __execCtrlBlock, bx ; execution control block
defbytes _filenameArg, 128 ; isolate arg
push di
pop di
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; scan remainder of command line for pipe, stdin and stdout args
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_assignRedirect_06:
lea dx, offset [ _filenameArg ][ bp ] ; address of arg
getarg di, __contargarray ; continue argument array
_assignRedirect_08:
mov si, word ptr [ di ]
or si, si ; end of args ?
ifz _assignRedirect_36 ; yes -->
mov ax, word ptr [ si ] ; get arg assignment
cmp ax, '>>' ; append to stdout ?
ifz _assignRedirect_AppendStdOut ; yes -->
cmp al, '>' ; stdout ?
jz _assignRedirect_StdOut ; yes -->
cmp al, '<' ; stdin ?
jz _assignRedirect_StdIn ; yes -->
cmp al, '|' ; pipe ?
jz _assignRedirect_Pipe ; yes -->
inc di
inc di
jmp _assignRedirect_08 ; go to next -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; stdout
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_assignRedirect_StdOut:
storarg __contargarray, di ; continue argument array
call deleteArg ; kill > arg
call _asgnGetFileName ; arg to _filenameArg [dx]
xor cx, cx
Int21 CreateFile ; if not found, create
ifc _assignRedirect_Error ; just display error -->
push ax
mov bx, ax
mov cx, STDOUT
call _assignGetCurrHandle
getarg di, __execCtrlBlock
mov word ptr [ exCtrlStdOutHandle ][ bx ], ax ; save old handle
Int21 ForceFileHandle ; redirect stdout
pop bx ; this close frees file handle after
Int21 CloseFile ; force replicate handle
jmp _assignRedirect_06
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; stdin
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_assignRedirect_StdIn:
storarg __contargarray, di ; continue argument array
call deleteArg ; kill < arg
call _asgnGetFileName ; arg to _filenameArg [dx]
lea dx, offset [ _filenameArg ][ bp ] ; address of arg
Int21 OpenFile, OPEN_ACCESS_READONLY ; try to open file
ifc _assignRedirect_Error ; just display error -->
mov bx, ax
mov cx, STDIN
call _assignGetCurrHandle
getarg di, __execCtrlBlock
mov word ptr [ exCtrlStdInHandle ][ bx ], ax ; save old handle
Int21 ForceFileHandle ; redirect stdout
jmp _assignRedirect_06
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; pipe
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_assignRedirect_Pipe:
storarg __contargarray, di ; continue argument array
mov word ptr [ di ], 0000 ; place an end marker in arg list
mov bx, dx
mov byte ptr [ bx ], 0
mov cx, OPEN_ACCESS_READWRITE ; create read/write
Int21 CreateUniqueFile ; if not found, create
ifc _assignRedirect_Error ; just display error -->
push ax
mov bx, ax
mov cx, STDOUT
call _assignGetCurrHandle
getarg di, __execCtrlBlock
mov word ptr [ exCtrlStdOutHandle ][ di ], ax ; save old handle
Int21 ForceFileHandle ; redirect stdout
pop bx ; this close frees file handle after
Int21 CloseFile ; force replicate handle
getarg di, __contargarray ; continue argument array
getarg bx, __execCtrlBlock ; execution control block
mov word ptr [ exCtrlArgArray. _pointer ][ bx ], di
or word ptr [ exCtrlFlags ][ bx ], exCtrlPiped ; say arg is piped.
jmp _assignRedirect_36 ; exit -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; append stdout
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_assignRedirect_AppendStdOut:
storarg __contargarray, di ; continue argument array
call deleteArg ; kill > arg
call deleteArg ; kill > arg
call _asgnGetFileName ; arg to _filenameArg [dx]
Int21 OpenFile, OPEN_ACCESS_READWRITE ; try to open file
jnc _assignRedirect_Append_08
cmp ax, errFileNotFound ; if other than not found
jnz _assignRedirect_Error ; just display error -->
xor cx, cx
lea dx, offset [ _filenameArg ][ bp ] ; address of arg
Int21 CreateFile ; if not found, create
jc _assignRedirect_Error ; just display error -->
_assignRedirect_Append_08:
push ax
xor cx, cx
xor dx, dx
mov bx, ax
Int21 MoveFilePointer, SEEK_END ; point to end of file
pop bx
push bx
mov cx, 2
mov dx, offset RxDOS_NewLine
Int21 WriteFile ; write CRLF
mov cx, STDOUT
call _assignGetCurrHandle
getarg bx, __execCtrlBlock
mov word ptr [ exCtrlStdOutHandle ][ bx ], ax ; save old handle
pop bx
push bx
Int21 ForceFileHandle ; redirect stdout
pop bx
Int21 CloseFile
jmp _assignRedirect_06
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; redirection error
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_assignRedirect_Error:
call DisplayError
stc
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_assignRedirect_36:
getarg di, __argarray ; argument array
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Kill Arg From List ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; cx handle whose value we want ;
; ax value of handle returned ;
;...............................................................;
_assignGetCurrHandle:
push es
push si
push bx
push cx
Int21 GetPSPAddress
pop si ; restore handle offset
mov es, bx ; set PSP address
les bx, dword ptr es:[ pspFileHandlePtr ] ; point to file handles
mov al, byte ptr es:[ bx + si ] ; recover existing handle
xor ah, ah
pop bx
pop si
pop es
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Copy Arg ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; si pointer to argument ;
; di pointer to copy location ;
; ;
; Returns: ;
; zr no characters copies ;
;...............................................................;
_copyArg:
or si, si
jz _copyArg_36
or cx, cx ; address of next arg zero ?
sub cx, si ; real length
_copyArg_08:
lodsb ; get character
stosb
or al, al
jz _copyArg_36
loop _copyArg_08
_copyArg_36:
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Get Filename From A Piped Or Redirected Argument ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; di points to arg list ;
; dx destination where to copy arg ;
; ;
; arg is removed from arg list (it is deleted) once copied ;
;...............................................................;
_asgnGetFileName:
push ax
push dx
push di
mov cx, word ptr [ di + 2 ] ; get arg that follows
mov si, word ptr [ di ] ; get current arg
mov di, dx
call _copyArg
pop di
call deleteArg ; kill arg
pop dx
pop ax
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Close Redirected Std Device ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; al restore value for handle (or -1) ;
; bx stdout or stdin ;
;...............................................................;
_CloseRedirectedDevice:
cmp al, -1 ; std device redirected ?
jz _closeRedirect_42 ; no -->
push es
push bx
push ax
Int21 CloseFile ; close std device
Int21 GetPSPAddress
pop ax
pop si
mov es, bx ; set PSP address
les bx, dword ptr es:[ pspFileHandlePtr ] ; point to file handles
xchg al, byte ptr es:[ bx + si ] ; recover existing handle
pop es
_closeRedirect_42:
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Lookup Argument ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ds:si pointer to argument (term by a null or switch char) ;
; cs:di pointer to supported commands ;
; ;
; Returns: ;
; bx pointer to command execution address ;
; cy argument not supported internally ;
;...............................................................;
CmndLookup:
push di
push si
inc di
inc di ; point to arg that follows
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; skip leading @ sign
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cmp byte ptr [ si ], '@' ; command begins with @ sign ?
jnz cmndLookup_12 ; no -->
inc si ; skip @ sign
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; compare argument against table
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cmndLookup_12:
mov al, byte ptr [ si ] ; from command
inc si
cmp al, ' '+1 ; if end of command
jc cmndLookup_18 ; see if all characters match -->
cmp al, byte ptr [ _SwitchChar ] ; switch character ?
jz cmndLookup_18 ; yes, end of arg -->
call _CmndParse_Break ; parse break ?
jz cmndLookup_18 ; yes, end of arg -->
call _lowerCase ; lower case ...
cmp al, byte ptr cs:[ di ] ; compare
jnz cmndLookup_18 ; if not this command -->
inc di ; else keep looking
jmp cmndLookup_12
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; if end, see if end of both args
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cmndLookup_18:
cmp byte ptr cs:[ di ], 0 ; end of command ?
jnz cmndLookup_28 ; not this command then -->
dec si
mov al, byte ptr [ si ] ; get last character
cmp al, ' '+1 ; end of command ?
jc cmndLookup_20 ; yes -->
cmp al, byte ptr [ _SwitchChar ] ; end of command ?
jz cmndLookup_20 ; yes -->
call _CmndParse_Break ; parse break ?
jz cmndLookup_20 ; yes -->
cmp al, '.' ; end of command ?
jz cmndLookup_20 ; yes -->
cmp al, '/' ; end of command ?
jz cmndLookup_20 ; yes -->
cmp al, '\' ; end of command ?
jnz cmndLookup_28 ; not this command -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; return valid arg
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cmndLookup_20:
pop ax ; leave si pointing at end
pop di
mov bx, word ptr cs:[ di ] ; where to execute
cmp byte ptr [ si ], '\' ; command ends with \ ?
clc ; NoCarry
jmp short cmndLookup_36
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; find next entry in table
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cmndLookup_28:
inc di
cmp byte ptr cs:[ di ], 0 ; end of command ?
jnz cmndLookup_28 ; keep looking -->
pop si
pop bx ; don't care about saved di
inc di ; get next word
cmp word ptr cs:[ di ], -1 ; end of command table ?
jnz cmndLookup ; no, lookup next -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; return invalid arg
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cmndLookup_32:
stc
mov bx, offset _NotValidCommand ; default not valid command
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cmndLookup_36:
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Count Number of Arguments ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:di pointer to argument array ;
; ;
; Returns: ;
; ax number of arguments in arg array ;
;...............................................................;
CountArgs:
push es
push di
push cx
mov cx, 64
setES ss
CountArgs_06:
cmp word ptr ss:[ di ], 0000 ; terminating arg ?
jz CountArgs_08 ; yes, done -->
inc di
inc di ; next arg
loop CountArgs_06 ; else, keep looking -->
CountArgs_08:
mov ax, 64
sub ax, cx ; # arguments
pop cx
pop di
pop es
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Pre Process Command Line ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:di pointer to argument array ;
; ;
; Returns: ;
; cy too many arguments message output ;
;...............................................................;
CheckNoArgs:
xor dx, dx ; no args
xor bx, bx ; no switches
jmp short PreProcessCmndLine ; check
CheckOneArg:
mov cx, 0001 ; must have one arg
mov dx, 0001 ; must have one arg
xor bx, bx ; no switches
jmp short PreProcessCmndLine ; check
CheckOptOneArg:
mov cx, 0000 ; must have none,
mov dx, 0001 ; or one arg
xor bx, bx ; no switches
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Pre Process Command Line ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:di pointer to argument array ;
; cx acceptable min # args ;
; dx acceptable max # args ;
; bx pointer to switches ;
; ;
; Returns: ;
; cy too many arguments message output ;
;...............................................................;
PreProcessCmndLine:
push di
push cx
push dx
call _GetSwitches ; switches ok ?
jc _preProcessCmndLine_08 ; no -->
pop dx
pop cx
push dx
push cx
call CountArgs ; see how many args remain
call _TooManyArguments ; too many still left ?
jc _preProcessCmndLine_08 ; yes -->
call nullTerminateArgs ; null terminate args
or ax, ax ; how many args passed
_preProcessCmndLine_08:
pop dx
pop cx
pop di
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Tests for Too Many Arguments ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:di pointer to argument array ;
; ax actual argument count ;
; cx acceptable min # args ;
; dx acceptable max # args ;
; ;
; Returns: ;
; cy too many arguments message output ;
;...............................................................;
_TooManyArguments:
cmp ax, dx ;
jz _TooManyArguments_08 ; if expected # args -->
jg _TooManyArguments_06 ; if greater than expected -->
cmp ax, cx
jge _TooManyArguments_08 ; if within min/max
_TooManyArguments_06:
push di
push ax
push cx
mov dx, offset CmndError_TooManyParameters
Call DisplayLine
pop cx
push cx
add cx, cx
add di, cx ; argument ptr that is extra
mov dx, word ptr ss:[ di ] ; get arg address
call DisplayLine ; show arg
pop cx
pop ax
pop di
stc
_TooManyArguments_08:
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Test/ Process Switches ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:di pointer to argument array ;
; bx pointer to switches to process (or null) ;
; ;
; Returns: ;
; cy if invalid use of switches ;
; ;
; Otherwise, switch array passed is filled with info. ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Switch array consists of a switch letter followed by: ;
; ;
; 'x' switch letter ;
; flags type of data value expected ;
; min min value expected ;
; max max value expected ;
; actual actual value passed in command ;
; ;
; a flag bit is set if the flag was encountered in cmnd. ;
;...............................................................;
_GetSwitches:
Entry
def _switches, bx
push di
push si
push cx
or bx, bx ; switches expected ?
jz _getSwitches_06 ; no -->
call _initSwitchTable ; init switches expected
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; walk through all args
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_getSwitches_06:
mov si, word ptr ss:[ di ] ; get arg
or si, si ; is it a null arg ?
jz _getSwitches_36 ; yes, exit -->
mov al, byte ptr ss:[ si ] ; get value at arg
cmp al, byte ptr [ _SwitchChar ] ; switch arg ?
jnz _getSwitches_12 ; no -->
getarg bx, _switches
or bx, bx ; any switches allowed ?
jz _getSwitches_24 ; if not allowed, drop from list
mov ax, word ptr ss:[ si + 1 ] ; get switch characters
call _matchSwitch ; is this switch valid ?
jc _getSwitches_24 ; not allowed -->
or word ptr [ swFlags ][ bx ], SW_SWITCHSET ; switch is set
call deleteArg ; remove this argument
jz _getSwitches_36 ; if no more args -->
_getSwitches_12:
inc di
inc di
jmp _getSwitches_06
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; switch is illegal
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_getSwitches_24:
push si ; save argument ptr
mov dx, offset CmndError_BadSwitch
call DisplayLine ; error message
pop dx
call DisplayLine ; show arg
stc
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; done
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_getSwitches_36:
pop cx
pop si
pop di
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Match Switch ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; al character ;
; bx switch table ;
; ;
; Returns: ;
; bx pointer to matchin switch entry ;
; cy match not found ;
;...............................................................;
_matchSwitch:
call _lowerCase
_matchSwitch_04:
cmp al, byte ptr cs:[ bx ]
jz _matchSwitch_08
add bx, sizeSWITCHENTRY ; next entry
cmp byte ptr cs:[ bx ], -1 ; end of table ?
jnz _matchSwitch_04 ; not yet -->
stc
_matchSwitch_08:
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Init Switch Table ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; bx switch table ;
;...............................................................;
_initSwitchTable:
push bx
_initSwitchTable_04:
cmp byte ptr cs:[ bx ], -1 ; end of table ?
jz _initSwitchTable_08 ; yes, all done -->
and word ptr cs:[ swFlags ][ bx ], not SW_SWITCHSET
add bx, sizeSWITCHENTRY ; next entry
jmp _initSwitchTable_04
_initSwitchTable_08:
pop bx
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Delete Argument ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:di argument list ;
;...............................................................;
deleteArg:
push di
cmp word ptr [ di ], 0000 ; at end of list ?
jz deleteArg_12 ; yes -->
deleteArg_08:
mov ax, word ptr [ di+2 ] ; get arg
mov word ptr [ di ], ax ; and move it
inc di
inc di
or ax, ax ; any more ?
jnz deleteArg_08 ; yes -->
cmp word ptr [ di+2 ], 0000 ; two args reqd to actually end copy
jnz deleteArg_08 ; not yet -->
deleteArg_12:
pop di
cmp word ptr [ di ], 0000 ; at end of list ?
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Null Terminate Args ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:di argument list ;
;...............................................................;
nullTerminateArgs:
push di
push ax
nullTerminateArgs_04:
mov si, word ptr [ di ]
or si, si ; more args ?
jz nullTerminateArgs_12 ; no -->
nullTerminateArgs_06:
lodsb ; get character
cmp al, ' '+1 ; space or control character ?
jc nullTerminateArgs_10 ; yes -->
cmp al, byte ptr [ _SwitchChar ] ; switch character ?
jz nullTerminateArgs_10 ; yes -->
call _CmndParse_Break ; parse break ?
jnz nullTerminateArgs_06 ; no, go to next char -->
nullTerminateArgs_10:
mov byte ptr [ si-1 ], 0 ; place null terminator
inc di
inc di
jmp nullTerminateArgs_04
nullTerminateArgs_12:
pop ax
pop di
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Replace Temporary Variables ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:si points to null terminated string ;
; ;
; Returns: ;
; cx length of new string ;
;...............................................................;
ReplaceTempVariables:
Entry
def _stringPointer, si
def _deleteFrom
defbytes _tempVar, 128
push di
push si
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; scan for % argument
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_replaceTempVar_08:
lodsb ; scan for % symbol
or al, al ; null terminator ?
ifz _replaceTempVar_36 ; yes -->
cmp al, '%' ; percent character ?
jnz _replaceTempVar_08
mov al, byte ptr [ si ] ; get character immed after
or al, al ; null terminator ?
ifz _replaceTempVar_36 ; yes -->
cmp al, '%' ; %% case ?
jz _replaceTempVar_PercentPercent ; yes -->
dec si ; backup over %
cmp al, '9'+1 ; outside arg values ?
jnc _replaceTempVar_EnvVariable ; yes -->
sub al, '0' ; outside argument values ?
jc _replaceTempVar_EnvVariable ; yes -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; numeric argument
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
mov cx, 2 ; bytes to delete
call deleteString ; delete cx bytes at si
xor ah, ah
cmp ax, word ptr [ RxDOS_BatchFile. batchNumArgs ]
jge _replaceTempVar_16 ; just delete arg -->
add ax, ax ; index pointer
mov di, ax
mov di, word ptr [ RxDOS_BatchFile. batchArgPtrs ][ di ]
or di, di
jz _replaceTempVar_16 ; if no arg value -->
call insertString ; insert arg at [ di ]
_replaceTempVar_16:
jmp _replaceTempVar_08
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; %% case
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_replaceTempVar_PercentPercent:
mov cx, 1
call deleteString ; delete cx bytes at si
jmp _replaceTempVar_08
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; environment variable
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_replaceTempVar_EnvVariable:
lea di, offset [ _tempVar ][ bp ]
storarg _deleteFrom, si
inc si ; skip init %
_replaceEnvVariable08:
lodsb ; scan for next % symbol
stosb ; save at _tempvar
or al, al ; null terminator ?
jz _replaceTempVar_36 ; yes -->
cmp al, '%' ; percent character ?
jnz _replaceEnvVariable08 ; keep searching -->
mov word ptr [ di-1 ], '=' ; cancel trailing %
mov cx, si
sub cx, word ptr [ _deleteFrom ][ bp ] ; delete from
push si
push cx ; delete length
lea si, offset [ _tempVar ][ bp ]
call searchEnvVariable ; environment string found ?
jnz _replaceEnvVariable36 ; not found -->
pop cx
push cx ; length to delete
mov si, word ptr [ _deleteFrom ][ bp ] ; delete from
call deleteString ; delete cx bytes at si
push ds
mov si, di
add si, dx ; contents of variable
mov ds, word ptr [ _EnvSegment ] ; point to segment
lea di, offset [ _tempVar ][ bp ] ; where to copy
call _CopyString ; copy null term string
pop ds
mov si, word ptr [ _deleteFrom ][ bp ] ; delete from
lea di, offset [ _tempVar ][ bp ] ; where to copy
call insertString ; insert
_replaceEnvVariable36:
pop cx
pop si
jmp _replaceTempVar_08
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; done
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_replaceTempVar_36:
xor ax, ax
mov cx, -1
getarg di, _stringPointer
repnz scasb
neg cx
sub cx, 2
pop si
pop di
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Replace 'For' Variable ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:si points to null terminated string ;
; ss:bx points to null terminated replacement string ;
; al replacement letter ;
; ;
; Returns: ;
; cx length of new string ;
;...............................................................;
ReplaceForVariables:
Entry
def _stringPointer, si
def _replaceText, bx
def _replaceVar
push di
push si
call _lowerCase ; replace vars in lower case
mov word ptr [ _replaceVar ][ bp ], ax ; replace variable to ah
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; scan for % argument
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_replaceForVar_08:
lodsb ; scan for % symbol
or al, al ; null terminator ?
ifz _replaceForVar_36 ; yes -->
cmp al, '%' ; percent character ?
jnz _replaceForVar_08
mov al, byte ptr [ si ] ; get character immed after
call _lowerCase
cmp al, byte ptr [ _replaceVar ][ bp ] ; same as var requested ?
jnz _replaceForVar_08 ; not yet -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; numeric argument
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
dec si ; backup over %
mov cx, 2 ; bytes to delete
call deleteString ; delete cx bytes at si
mov di, word ptr [ _replaceText ][ bp ] ; insert text
call insertString ; insert [ di ] arg
jmp _replaceForVar_08
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; done
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_replaceForVar_36:
xor ax, ax
mov cx, -1
getarg di, _stringPointer
repnz scasb
neg cx
sub cx, 2
pop si
pop di
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Delete String ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:si points inside string ;
; cx bytes to delete ;
;...............................................................;
deleteString:
push di
push ax
push si
push cx
or cx, cx ; if null call
jz deleteString_36 ; nothing to do -->
deleteString_08:
lodsb ; test for null term
or al, al
jz deleteString_32
loop deleteString_08
pop cx
pop si
push si
push cx
mov di, si
add si, cx ; skip pointer
deleteString_12:
lodsb ; copy byte
stosb
or al, al
jnz deleteString_12
dec si ; point to null byte
deleteString_32:
mov byte ptr [ si ], 0
deleteString_36:
pop cx
pop si
pop ax
pop di
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Insert String ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:si points inside string ;
; ds:di points to insert string (null term) ;
; ;
; Returns: ;
; ss:si points to char past insert string ;
;...............................................................;
insertString:
push cx
push ax
push di
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; compute length of insert string
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
xor ax, ax
mov cx, -1
repnz scasb ; search length of insert string
neg cx ; make len-1 positive
sub cx, 2 ; kill null string arg
sub di, 2 ; point to last valid byte before null
push di ; end of arg pointer
push cx ; length of insert string
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; compute length of master string
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
xor ax, ax
mov cx, -1
mov di, si
repnz scasb ; search length of insert string
neg cx ; make len-1 positive
dec cx ; kill null string arg
dec di
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; open string
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
std ; copy reverse direction
pop ax
push ax ; length of insert string
mov si, di ;
add di, ax ; where to copy to
rep movsb
pop cx
pop si
push di ; save return pointer
rep movsb ; insert string
cld ; restore direction
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; done
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
pop si ; return pointer - 1
inc si
pop di
pop ax
pop cx
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Get Number at String ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Input: ;
; ss:si pointer to text ;
; ;
; Returns: ;
; ax contains value ;
; cy if value contained text ;
;...............................................................;
_GetNumber:
xor dx, dx
_GetNumber_04:
lodsb
cmp al, ' '+1 ; end of string ?
jc _GetNumber_16 ; yes, exit ok -->
cmp al, '9'+1 ; valid number ?
jnc _GetNumber_14 ; no, error exit -->
sub al, '0' ; valid number ?
jc _GetNumber_14 ; no, error exit -->
and ax, 15
push ax
mov ax, dx
add dx, dx ; 2
add dx, dx ; 4
add dx, ax ; 5
add dx, dx ; 10
pop ax
add dx, ax ; add digit
jmp _GetNumber_04 ; continue -->
_GetNumber_14:
xor ax, ax
stc
ret
_GetNumber_16:
mov ax, dx
or ax, ax
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Lower Case Character (AL) ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; al character ;
;...............................................................;
_lowerCase:
cmp al, 'A'
jc _lowerCase_10
cmp al, 'Z'+1
jnc _lowerCase_10
or al, 20h ; lower case
_lowerCase_10:
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Lower Case String ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; stack string pointer ;
; ;
; Returns: ;
; di points to end (null) byte ;
; cx characters in string ;
;...............................................................;
_lowerCaseString:
Entry 2
darg _string
push es
xor cx, cx
getdarg es, di, _string
_lowerCaseString_08:
mov al, byte ptr es:[ di ]
or al, al
jz _lowerCaseString_16
cmp al, 'A'
jc _lowerCaseString_10
cmp al, 'Z'+1
jnc _lowerCaseString_10
or al, 20h ; lower case
_lowerCaseString_10:
mov byte ptr es:[ di ], al
inc di
inc cx
jmp _lowerCaseString_08
_lowerCaseString_16:
pop es
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Upper Case Character (AL) ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; al character ;
;...............................................................;
_upperCase:
cmp al, 'a'
jc _upperCase_10
cmp al, 'z'+1
jnc _upperCase_10
and al, not 20h ; upper case
_upperCase_10:
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Compare Sub Strings ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; si points to a null terminated string ;
; di points to longer string ;
; ;
; Returns: ;
; zr strings match regardless of case ;
;...............................................................;
_compareSubString:
mov al, byte ptr [ si ]
or al, al
jz _compareSubString_08
inc si
call _lowerCase
mov bl, al
mov al, byte ptr [ di ]
inc di
call _lowerCase
cmp al, bl
jz _compareSubString
_compareSubString_08:
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Copy String ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; si points to a null terminated string ;
; di points to destination string ;
;...............................................................;
_copyString:
lodsb ; copy character
stosb ; copy character
or al, al ; until zero byte
jnz _copyString
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Locate End Of String ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; di points to a null terminated string ;
;...............................................................;
_endofString:
push ax
push cx
xor ax, ax
mov cx, -1
repnz scasb ; locate null terminator
dec di ; backup over null byte
pop cx
pop ax
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Append Path Name ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; si points to a null terminated string ;
; di points to a null terminated string ;
;...............................................................;
_AppendPathName:
cmp byte ptr [ di ], 00
jz _AppendPathName_12 ; if no path given, don't search -->
xor ax, ax
mov cx, -1
repnz scasb
dec di ; backup to null
cmp byte ptr [ di - 1 ], '\' ; does path have terminating \ ?
jz _AppendPathName_12 ; yes, no need to add another -->
_AppendPathName_08:
mov byte ptr [ di ], '\' ; add terminating \
inc di
_AppendPathName_12:
call _CopyString
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Search Env String ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Input: ;
; ds:si points to input command string ;
; ;
; Output: ;
; ds:si points to end of input string (imm after =) ;
; es:di points to name value in env string ;
; dx offset in env variable to value past = sign ;
; nz env variable not found ;
;...............................................................;
searchEnvVariable:
Entry
def _search, si ; search text
def _envbegpointer, 0000 ; located env variable
push es
mov es, word ptr [ _EnvSegment ] ; point to segment
xor di, di
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; search through each item
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
searchEnvVariable_08:
storarg _envbegpointer, di ; located env variable
getarg si, _search ; get search text pointer
cmp byte ptr es:[ di ], 00 ; end of env area ?
jz searchEnvNotFound ; not found -->
searchEnvVariable_12:
mov al, byte ptr [ si ]
or al, al ; if end string -->
jz searchEnvVariable_Next ; not equal, skip to next -->
call _upperCase ; conv to upper case
mov ah, al
mov al, byte ptr es:[ di ] ; compare
call _upperCase ; conv to upper case
cmp ah, al ; compare
jnz searchEnvVariable_Next ; not equal, skip to next -->
inc si
inc di
cmp al, '=' ; at equal sign ?
jz searchEnvVariableFound ; we have search item -->
cmp byte ptr es:[ di-1 ], 00 ; end of env string ?
jnz searchEnvVariable_12 ; continue -->
jmp searchEnvVariable_08
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; skip to next env variable
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
searchEnvVariable_Next:
inc di
cmp byte ptr es:[ di-1 ], 00 ; end of env string ?
jnz searchEnvVariable_Next ; continue -->
jmp searchEnvVariable_08
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; item not found
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
searchEnvNotFound:
mov ax, es
or ax, ax ; not zero means not found
jmp short searchEnvReturn
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; item found
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
searchEnvVariableFound:
mov dx, word ptr [ _envbegpointer ][ bp ] ; return start pointer
sub di, dx ; distance from beg pointer
xchg di, dx ; return offset in dx
xor ax, ax
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
searchEnvReturn:
pop es
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Delete Env Variable ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; di pointer to env entry to delete ;
; ;
; Returns: ;
; di pointer to end byte of environment ;
; ax bytes available in Environment ;
;...............................................................;
deleteEnvVariable:
push es
mov es, word ptr [ _EnvSegment ] ; point to segment
cmp byte ptr es:[ di ], 00 ; at end of env block ?
jz deleteEnvVariable_36 ; yes, don't delete -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; locate start of next string
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
mov si, di ; save di pointer
deleteEnvVariable_08:
inc si
cmp byte ptr es:[ si-1 ], 00 ; locate end of this string
jnz deleteEnvVariable_08 ; continue -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; is this end of env block ?
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
deleteEnvVariable_12:
mov byte ptr es:[ di ], 00 ; put end mark.
cmp byte ptr es:[ si ], 00 ; at end of env block ?
jz deleteEnvVariable_36 ; yes, end of delete -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; copy a string
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
deleteEnvVariable_16:
mov al, byte ptr es:[ si ]
stosb ; copy byte
inc si
or al, al ; did we copy a null terminator ?
jnz deleteEnvVariable_16 ; not yet -->
jmp deleteEnvVariable_12 ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
deleteEnvVariable_36:
mov ax, word ptr [ _EnvSize ]
sub ax, di ; space left
pop es
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Insert Env Variable ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; si pointer to text to insert into environment ;
; di must point to end null byte of environment block ;
; ;
; Returns: ;
; ax bytes remaining in Environment ;
; cy if could not add to environment block ;
;...............................................................;
insertEnvVariable:
Entry
def endPointer, di
push es
mov es, word ptr [ _EnvSegment ] ; point to segment
mov cx, word ptr [ _EnvSize ]
sub cx, di ; bytes available
jle insertEnvVariable_36 ; if none -->
insertEnvVariable_08:
lodsb
stosb ; copy byte
or al, al ; all done ?
jz insertEnvVariable_36 ; yes -->
loop insertEnvVariable_08
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; can't insert (insufficient space)
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
stc ; error, if not all copied
mov ax, 0000
getarg di, endPointer ; restore pointer to old end
mov byte ptr es:[ di ], 00 ; restore end pointer
pop es
Return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
insertEnvVariable_36:
mov ax, word ptr [ _EnvSize ]
sub ax, di ; space left
mov byte ptr es:[ di ], 00 ; put end pointer
pop es
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Find Program or Bat File ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:si pointer to name (not null terminated) ;
; ;
; Returns: ;
; cy not found anywhere in path ;
; ax contains type of program found ;
; 0000 - program is a batch file ;
; 0001 - program is a com or exe file ;
; bx contains handle to file ;
;...............................................................;
_findProgram:
Entry
def _pathArg, dx ; where to store path
def _pathpointer ; PATH=, if any
def _endofname
def _endofpathname
def _dontSearch, false
defbytes _execname, 128
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; isolate name from rest of command line
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
lea di, offset [ _execname ][ bp ] ; pointer to copy field
_findProgram_08:
lodsb ; get character
stosb ; copy it
cmp al, ' '+1 ; space or control character ?
jc _findProgram_20 ; yes -->
cmp al, '|' ; pipe character ?
jz _findProgram_20 ; yes -->
cmp al, '*' ; wild character ?
ifz _findProgram_Error ; yes -->
cmp al, '?' ; wild character ?
ifz _findProgram_Error ; yes -->
cmp al, byte ptr [ _SwitchChar ] ; switch character ?
jz _findProgram_20 ; yes -->
cmp al, '\' ; file name contains path info ?
jz _findProgram_12 ; don't search path= -->
cmp al, '/' ; file name contains path info ?
jnz _findProgram_14 ; don't search path= -->
_findProgram_12:
mov byte ptr [ _dontSearch ][ bp ], true
_findProgram_14:
call _CmndParse_Break ; parse break ?
jnz _findProgram_08 ; yes -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; search through current directory first
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_findProgram_20:
dec di
mov byte ptr [ di ], 0 ; place null terminator
lea si, offset [ _execname ][ bp ] ; pointer to copy field
mov di, word ptr [ _pathArg ][ bp ] ; pointer to path arg
mov word ptr [ _endofpathname ][ bp ], di ; save end of path name pointer
call _CopyString ; append filename
mov dx, word ptr [ _pathArg ][ bp ] ; pointer to path arg
Int21 FindFirstFile ; locate file
jnc _findProgram_50 ; if located -->
mov si, offset RxDOS_PathSpec
call searchEnvVariable ; locate PATH=
add di, dx ; address after =
storarg _pathpointer, di ; location of path statement
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; search through search order
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_findProgram_30:
lea si, offset [ _execname ][ bp ] ; pointer to copy field
getarg di, _endofpathname ; where to copy name
call _CopyString ; append filename
dec di
mov word ptr [ _endofname ][ bp ], di ; save end name pointer
mov si, offset RxDOS_ExecOrder ; look for names in order, current dir
_findProgram_32:
getarg di, _endofname
call _CopyString ; copy extension
push si ; save pointer
mov dx, word ptr [ _pathArg ][ bp ] ; pointer to path arg
Int21 FindFirstFile ; locate file
pop si ; restore si
jnc _findProgram_50 ; if located -->
cmp byte ptr [ si ], -1 ; end of search order list ?
jnz _findProgram_32 ; not yet -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; locate next search path
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cmp byte ptr [ _dontSearch ][ bp ], true ; search path ?
jz _findProgram_CantFind ; no, can't find -->
push ds
mov ds, word ptr [ _EnvSegment ]
mov si, word ptr [ _pathpointer ][ bp ] ; path=
mov di, word ptr [ _pathArg ][ bp ] ; pointer to path arg
_findProgram_36:
lodsb
or al, al
jz _findProgram_38
cmp al, ';'
jz _findProgram_40
stosb
jmp _findProgram_36
_findProgram_38:
mov byte ptr [ _dontSearch ][ bp ], true ; don't search any longer (end of path)
_findProgram_40:
storarg _pathpointer, si ; save end of path search
pop ds ; restore ds
mov al, '\'
cmp al, byte ptr [ di - 1 ] ; pathname terminated by \ ?
jz _findProgram_42 ; yes -->
stosb ; add \ to pathname
_findProgram_42:
storarg _endofpathname, di ; save path name
jmp _findProgram_30
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; file found, determine if .exe or .com
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_findProgram_50:
mov si, offset [ RxDOS_DTA. findFileName ]
_findProgram_52:
lodsb ; get filename character
or al, al ; end of name ?
jz _findProgram_56 ; yes, assume .bat -->
cmp al, '.' ; extension located ?
jnz _findProgram_52 ; no, keep scanning -->
lodsw ; get filename character
mov cx, ax
or cx, ' ' ; force lower case
lodsb
xor ah, ah
or al, ' ' ; lower case
add cx, ax ; checksum
mov ax, _EXE ; _exe
cmp cx, ( 'xe' + 'e' ) ; exe ?
jz _findProgram_62 ; probably -->
mov ax, _COM ; _com
cmp cx, ( 'oc' + 'm' ) ; com ?
jz _findProgram_62 ; probably -->
_findProgram_56:
mov ax, _BAT ; _com
_findProgram_62:
or ax, ax ; no carry
Return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; error
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_findProgram_CantFind:
_findProgram_Error:
stc
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; return volume name ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; al is disk to read volume ;
; di pointer to volume name (in DTA) ;
; cy drive has no volume name ;
;...............................................................;
returnVolumeName:
cmp al, 'Z'-40h
jnc returnVolumeName_08
or al, al ; default disk ?
jnz returnVolumeName_06 ; no -->
Int21 CurrentDisk
inc al ; a=1, ...
returnVolumeName_06:
add al, 'a'-1
returnVolumeName_08:
mov di, offset RxDOS_RootDirectory - 2
mov byte ptr [ di ], al
mov dx, di
mov cx, ATTR_VOLUME
mov di, offset [ RxDOS_DTA. findFileName ]
mov byte ptr [ di ], 0
Int21 FindFirstFile ; find volume name
mov dx, 0 ; assume no error
jnc returnVolumeName_18 ; return zero (found )
mov dx, 1 ; else assume not found error
cmp al, errPathNotFound ; if path not found,
jnz returnVolumeName_18 ; then return NZ -->
stc
ret
returnVolumeName_18:
or dx, dx
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Get Error Code ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ax error code ;
;...............................................................;
DisplayError:
push bx
cmp ax, CmndError_RefTableEntries
jnc DisplayError_08
mov bx, ax
add bx, bx
add bx, offset CmndError_TextReferenceTable
mov dx, word ptr cs:[ bx ] ; get address of message
cmp dx, 0000 ; error not defined ?
jz DisplayError_08
call DisplayErrorMessage ; display message
DisplayError_08:
pop bx
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Display Error Message ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; cs:dx points to error message ;
;...............................................................;
DisplayErrorMessage:
call DisplayLine ; print line
call CRLF ; new line
stc
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Display Cr/Lf ;
;...............................................................;
CRLF:
push es
push dx
setES ds
mov dx, offset RxDOS_NewLine
call DisplayLine ; cr/lf
pop dx
pop es
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Display Line ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; es:si points to message ;
;...............................................................;
DisplayLine:
push si
mov si, dx
DisplayLine_08:
mov dl, byte ptr es:[ si ]
or dl, dl ; end of string ?
jz DisplayLine_16 ; yes -->
inc si
Int21 DisplayOutput
cmp dl, 'J'-40h ; new line ?
jnz DisplayLine_08 ; no -->
call _Paginate ; account for line
call _CheckControlC ; see if control C
jnc DisplayLine_08 ; continue -->
DisplayLine_16:
pop si
clc
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Display Line Count ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; es:dx points to message ;
; cx characters ;
;...............................................................;
DisplayLineCount:
Entry
def _count, cx
push si
mov si, dx
DisplayLineCount_08:
mov dl, byte ptr es:[ si ]
inc si
Int21 DisplayOutput
cmp dl, 'J'-40h ; new line ?
jnz DisplayLineCount_12 ; no -->
call _Paginate ; account for line
call _CheckControlC ; see if control C
jc DisplayLineCount_16 ; if abort -->
DisplayLineCount_12:
dec word ptr [ _count ][ bp ]
jnz DisplayLineCount_08
DisplayLineCount_16:
pop si
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Paginate ;
;...............................................................;
_Paginate:
push si
call isStdOutAFile
jz _Paginate_14 ; yes, no pause needed -->
cmp byte ptr [ PageLines ], 00 ; page lines ?
jz _Paginate_14 ; don't worry about lines
inc word ptr [ LinesDisplayed ] ; incr lines displayed
call GetScreenLines
dec ax ; # lines on screen -1
cmp ax, word ptr [ LinesDisplayed ] ; beyond # screen lines ?
jg _Paginate_14 ; not yet -->
mov word ptr [ LinesDisplayed ], 0000 ; reset screen lines
call _Pause
_Paginate_14:
pop si
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Set Paging Mode ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; If value is 8000 (switch is set), then set Paging Mode. ;
; ;
;...............................................................;
setPagingMode:
mov byte ptr [ PageLines ], 00 ; paging mode
and ax, SW_SWITCHSET
jz setPagingMode_08
mov byte ptr [ PageLines ], -1 ; paging mode
mov word ptr [ LinesDisplayed ], 0000 ; # lines displayed, curr page
setPagingMode_08:
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Is StdOut A File ? ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Returns: ;
; zr stdout is a file ;
; nz stdout is NOT a file ;
;...............................................................;
isStdOutAFile:
mov bx, STDOUT
Int21 IoControl, 00h ; is device piped from a file ?
mov ax, 1 ; non-zero value
jc _isStdOutAFile_No ; we'll assume its not -->
test dx, 80h ; if bit 7 = 0, handle is a file
jnz _isStdOutAFile_No ; we'll assume its not -->
_isStdOutAFile_Yes:
xor ax, ax ; zero value if bat file
_isStdOutAFile_No:
or ax, ax
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Check Control C ;
;...............................................................;
_CheckControlC:
clc
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Scan Print Buffer ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; This routine accepts a variable number of arguments and for- ;
; mats an output buffer. It works very similar to C's sprintf ;
; function. ;
; ;
; The input buffer may contain imbedded formatting codes: ;
; ;
; %c insert character (pointer to character on stack) ;
; %s insert string (pointer to string on stack) ;
; %d insert decimal (pointer to decimal on stack) ;
; %ld insert long (pointer to long on stack) ;
; ;
; If a format command contains numbers, the number is inter- ;
; preted as a field width. The output value will be right ;
; aligned within the field width if the width is preceeded ;
; with a negative sign. Any characters that exceeds the field ;
; width is ignored. ;
; ;
; If a format command contains a comma, the number will be ;
; decimal edited. ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; stack argument ;
; . argument ;
; . argument ;
; stack argument ;
; stack format buffer ;
; stack output buffer ;
; ;
; Returns: ;
; dx pointer to output buffer ;
;...............................................................;
_sprintf:
Entry 2
arg _format
arg _output
def _args, 0000
def _varg
def _fieldwidth
def _fieldflags
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; scan/copy buffer
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
lea di, word ptr [ _format ][ bp ]
add di, 2 ; point to prev arg
storarg _varg, di ; save var arg pointer
mov si, word ptr [ _format ][ bp ]
mov di, word ptr [ _output ][ bp ]
_sprintf_06:
mov word ptr [ _fieldwidth ][ bp ], 0000 ; no width
mov word ptr [ _fieldflags ][ bp ], 0000 ; no flags
_sprintf_08:
lodsb ; get character
stosb ; copy to output
or al, al ; all done ?
ifz _sprintf_86 ; yes -->
cmp al, '%' ; format code ?
jnz _sprintf_08 ; not yet -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; format code
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
mov word ptr [ _fieldwidth ][ bp ], 0000 ; no width
mov word ptr [ _fieldflags ][ bp ], 0000 ; no flags
dec di ; kill format % in output
mov byte ptr [ di ], 0 ; stick a null code there
_sprintf_12:
lodsb ; get character that follows
call _lowerCase ; make it lower case
or al, al ; all done ?
ifz _sprintf_86 ; yes -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; is it long ?
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cmp al, 'l' ; long flag ?
jnz _sprintf_14 ; no -->
or word ptr [ _fieldflags ][ bp ], SPRINTF_LONGFLAG
jmp _sprintf_12
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; is it a left justify
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_sprintf_14:
cmp al, '-' ; left justify
jnz _sprintf_16 ; no -->
or word ptr [ _fieldflags ][ bp ], SPRINTF_LEFTALIGN
jmp _sprintf_12
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; is it a comma (decimal) delimeter ?
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_sprintf_16:
cmp al, ',' ; decimal delimeter ?
jnz _sprintf_18 ; no -->
or word ptr [ _fieldflags ][ bp ], SPRINTF_COMMADELIM
jmp _sprintf_12
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; is it a field width ?
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_sprintf_18:
cmp al, '9'+1 ; number ?
jnc _sprintf_22 ; no -->
cmp al, '0' ; number ?
jc _sprintf_22 ; no -->
and ax, 15 ; get number
mov dx, word ptr [ _fieldwidth ][ bp ] ; get width
add dx, dx ; x2
add dx, dx ; x4
add dx, word ptr [ _fieldwidth ][ bp ] ; x5
add dx, dx ; x10
add dx, ax
mov word ptr [ _fieldwidth ][ bp ], dx
jmp _sprintf_12
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; see if its a valid formatting code
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_sprintf_22:
cmp al, 'd' ; decimal output ?
jz _sprintf_26
cmp al, 'x' ; hex output ?
jz _sprintf_26
cmp al, 'c' ; character ?
jz _sprintf_32
cmp al, 's' ; string ?
jz _sprintf_36
cmp al, '%' ; percent percent ?
jz _sprintf_46
jmp _sprintf_06
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; decimal
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_sprintf_26:
push si
getarg si, _varg ; get variable arg ptr
mov si, word ptr [ si ] ; get argument pointer
add word ptr [ _varg ][ bp ], 2
inc word ptr [ _args ][ bp ]
;** doesn't support right justified
xor dx, dx
mov ax, word ptr [ si ] ; get number
test word ptr [ _fieldflags ][ bp ], SPRINTF_LONGFLAG
jz _sprintf_28
mov dx, word ptr [ si+2 ] ; get long
_sprintf_28:
mov bx, word ptr [ _fieldflags ][ bp ] ; flags
mov cx, word ptr [ _fieldwidth ][ bp ] ; width
call _sprintfNum ; convert numeric to ascii
pop si
jmp _sprintf_06
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; character
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_sprintf_32:
push si
getarg si, _varg ; get variable arg ptr
mov si, word ptr [ si ] ; get argument pointer
add word ptr [ _varg ][ bp ], 2
inc word ptr [ _args ][ bp ]
;** doesn't support right justified
mov cx, word ptr [ _fieldwidth ][ bp ] ; width
call _sprintfInitField
mov al, byte ptr [ si ]
stosb ; store character
pop si
mov cx, word ptr [ _fieldwidth ][ bp ] ; width
or cx, cx
ifz _sprintf_06
dec cx
call _sprintfPadField
jmp _sprintf_06
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; string
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_sprintf_36:
push si
getarg si, _varg ; get variable arg ptr
mov si, word ptr [ si ] ; get argument pointer
add word ptr [ _varg ][ bp ], 2
inc word ptr [ _args ][ bp ]
;** doesn't support right justified
mov cx, word ptr [ _fieldwidth ][ bp ] ; width
call _sprintfInitField
_sprintf_38:
lodsb
or al, al ; null terminator ?
jz _sprintf_40 ; yes -->
stosb
or cx, cx ; fixed count ?
jz _sprintf_38
loop _sprintf_38
_sprintf_40:
or cx, cx ; still more length to go ?
jz _sprintf_42 ; no -->
add di, cx ; advance field length
_sprintf_42:
pop si
jmp _sprintf_06
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; %
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_sprintf_46:
stosb
jmp _sprintf_06
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; all done
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_sprintf_86:
mov ax, word ptr [ _args ][ bp ]
add ax, ax ; # words left on stack
mov si, word ptr [ _output ][ bp ]
mov dx, si
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Convert Long (dx:ax) to Ascii ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; dx:ax long value ;
; cx size of field to right justify ;
; bx display option flags: ;
; 8000 insert decimal commas ;
; ;
;...............................................................;
_sprintfNum:
Entry
defbytes _decDisplay, 16
def _decimalflag, bx
def _fieldwidth, cx
def _spacing
push si
push di
call _sprintfInitField ; init field to spaces
mov byte ptr [ _spacing ][ bp ], 03 ; set spacing
lea di, offset [ _decDisplay ][ bp ]
push di
_sprintfNum_08:
mov cx, 10
call _div32 ; divide by 10
or cl, '0'
mov byte ptr [ di ], cl ; store character
inc di
mov cx, dx
or cx, ax ; more to go ?
jz _sprintfNum_10 ; no -->
test word ptr [ _decimalflag ][ bp ], SPRINTF_COMMADELIM
jz _sprintfNum_10 ; no -->
dec byte ptr [ _spacing ][ bp ] ; spacing break ?
jnz _sprintfNum_10 ; not yet -->
mov byte ptr [ _spacing ][ bp ], 03 ; set spacing
mov byte ptr [ di ], ',' ; store comma
inc di
_sprintfNum_10:
mov cx, dx
or cx, ax ; more to go ?
jnz _sprintfNum_08 ; yes -->
pop cx
sub di, cx ; total # chars output
mov cx, di ; length to cx
pop di
push di ; where to begin right justify
lea si, offset [ _decDisplay ][ bp ] ; where data stored
cmp word ptr [ _fieldwidth ][ bp ], 0000 ; left justified output ?
jz _sprintfNum_20 ; yes -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; right justified
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; be sure to blank fill field first
add di, word ptr [ _fieldwidth ][ bp ] ;
push di
_sprintfNum_16:
lodsb ; get character
dec di
mov byte ptr [ di ], al
loop _sprintfNum_16
pop di
jmp short _sprintfNum_32
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; left justified
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_sprintfNum_20:
lodsb ; get character
stosb
loop _sprintfNum_20
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; done
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_sprintfNum_32:
pop si ; drop saved di
pop si
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Init Field to Spaces ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; di pointer to buffer ;
; cx width of field ;
; bx 8000 if right justified ;
;...............................................................;
_sprintfInitField:
or cx, cx ; fixed count ?
jz _sprintfInitField_08 ; no -->
push di
push cx
push ax
mov al, ' '
rep stosb
pop ax
pop cx
pop di
_sprintfInitField_08:
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Pad Field ;
;...............................................................;
_sprintfPadField:
or cx, cx ; still more length to go ?
jz _sprintfPadField_08 ; no -->
add di, cx ; advance field length
_sprintfPadField_08:
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; 32 Bit Divide ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Input: ;
; ax:dx numerator ;
; cx divisor ;
; ;
;...............................................................;
_div32: or cx, cx ; protect from zero divisor
stc ; in case of error
jz _div32_return ; if so, just return with carry
push bx
mov bx, dx
xchg ax, bx
xor dx, dx
div cx
xchg ax, bx
div cx ; remainder will be in dx
mov cx, dx
mov dx, bx
pop bx
_div32_return:
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Get Screen Lines ;
;...............................................................;
GetScreenLines:
push ds
push bx
xor bx, bx
mov ds, bx
mov bx, offset 484h
mov al, byte ptr [ bx ] ; Video Rows
cbw ; extend to full word
inc al ; correct number
pop bx
pop ds
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Physical Screen Clear ;
;...............................................................;
PhysClearScreen:
call GetScreenLines
mov dh, al
mov dl, 80
mov ax, 0600h ; entire screen
mov bx, 7100h ; blue/white
mov cx, 0000h ; from home row
int 10h
mov ax, 0200h
mov bx, 0000h
mov dx, 0000h
int 10h ; position cursor
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Commands (Alphabetical) ;
;...............................................................;
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Break [ ON | OFF ] ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Sets, clears or reports on RxDOS break option. ;
; ;
;...............................................................;
_Break:
Entry
ddef __argarray, ss, di
def _args, ax
call CheckOptOneArg ; see if 1 arg
jc _BreakExit ; if error -->
or ax, ax ; any arguments ?
jz _BreakPrintcurrent ; none, print current status -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; test for On/ Off
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
mov si, word ptr [ di ] ; get single argument
mov di, offset RxDOS_OnOff
call CmndLookup ; lookup command
jc _BreakError ; if not on/off, print line -->
mov dl, bl
Int21 CtrlBreakCheck, setControlC ; set/clear Ctrl Break check
Return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; must specify on or off
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_BreakError:
mov dx, offset CmndError_MustSpecifyOnOff
call DisplayErrorMessage
Return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; print verify on/off value
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_BreakPrintcurrent:
Int21 CtrlBreakCheck, getControlC ; get/clear Ctrl Break check
mov bl, dl
xor bh, bh
add bx, bx
mov dx, word ptr [ _BreakOptions ][ bx ]
call DisplayLine
_BreakExit:
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Change Directory ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Unlike most other commands, cd command will be processed if ;
; part of the cd command, as in cd\... ;
; ;
; Usage: ;
; ss:di Arg Array ;
; ax Number of arguments in array ;
;...............................................................;
_Call:
Entry
def __argarray, di
def __progname, si
def __tempargptr
defbytes _pathArg, 128
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; find program
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
lea dx, offset [ _pathArg ][ bp ] ; where to return fully qualified path name
call _findProgram ; locate program or bat file
jc _call_12 ; if program not found -->
cmp ax, _BAT ; is it a bat program ?
jz _call_22 ; yes -->
mov di, word ptr [ __argarray ][ bp ]
; call _loadProgram ; else load and execute program
Return ; return
_call_12:
call _NotValidCommand ; not valid (not found )
Return ; return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; execute (call) batch
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_call_22:
lea dx, offset [ _pathArg ][ bp ] ; pointer to file name
Int21 OpenFile, 00h ; read only
push ax ; save batch file handle
xor cx, cx
xor dx, dx
mov bx, word ptr [ RxDOS_BatchFile. batchFileHandle ]
Int21 MoveFilePointer, SEEK_CUR ; get current position
mov word ptr [ RxDOS_BatchFile. batchFilePosition. _low ], ax
mov word ptr [ RxDOS_BatchFile. batchFilePosition. _high ], dx
mov si, offset RxDOS_BatchFile
mov di, word ptr [ RxDOS_PrevStackFrame ]
mov cx, sizeBATCH_ARGS
rep movsb ; copy current args to save area
sub word ptr [ RxDOS_PrevStackFrame ], sizeBATCH_ARGS
inc word ptr [ RxDOS_StackFrameNumEntries ]
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; setup batch file arguments
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
pop word ptr [ RxDOS_BatchFile. batchFileHandle ]
mov di, word ptr [ __argarray ][ bp ] ; arguments pointer
call nullTerminateArgs
mov di, offset ( RxDOS_BatchFile. batchArgStore )
mov word ptr [ RxDOS_BatchFile. batchNumArgs ], 0
mov si, word ptr [ __argarray ][ bp ] ; arguments pointer
storarg __tempargptr, si
_call_32:
getarg si, __tempargptr
mov si, word ptr [ si ] ; arg
or si, si ; null terminator ?
jz _call_36 ; then all done -->
add word ptr [ __tempargptr ][ bp ], 2
mov bx, word ptr [ RxDOS_BatchFile. batchNumArgs ]
add bx, bx
mov word ptr [ RxDOS_BatchFile. batchArgPtrs ][ bx ], di
mov word ptr [ RxDOS_BatchFile. batchArgPtrs + 2 ][ bx ], 0000
inc word ptr [ RxDOS_BatchFile. batchNumArgs ]
call _CopyString
jmp _call_32
_call_36:
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Change Directory ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Unlike most other commands, cd command will be processed if ;
; part of the cd command, as in cd\... ;
; ;
; Usage: ;
; ss:di Arg Array ;
; ax Number of arguments in array ;
;...............................................................;
_ChangeDir:
Entry
def _disk
ddef __argarray, ss, di
defbytes _tempstring, 128
call CheckOptOneArg ; see if 1 arg
ifc _changeDir_32 ; if switch not expected -->
jnz _changeDir_18 ; if argument passed -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; display current
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Int21 CurrentDisk ; get current disk
mov dl, al ; save drive letter
or al, 'a' ; drive
lea di, offset [ _tempstring + 3][ bp ]
mov byte ptr [ di - 3 ], al
mov byte ptr [ di - 2 ], ':'
mov byte ptr [ di - 1 ], '\'
inc dl
mov si, di
Int21 GetCurrentDirectory ; get current directory
push ss
push si ; where string
call _lowerCaseString
lea dx, offset _tempstring [ bp ]
call DisplayLine
Return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; change drive: directory
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_changeDir_18:
mov di, word ptr [ __argarray. _pointer ][ bp ]
mov si, word ptr ss:[ di ] ; pointer to lead argument
lea di, offset [ _tempstring ][ bp ]
mov word ptr [ di ], '\' ; init area
Int21 GetActualFileName ; expand name
mov di, word ptr [ __argarray. _pointer ][ bp ]
mov si, word ptr ss:[ di ] ; pointer to lead argument
cmp byte ptr [ si+1 ], ':' ; drive ?
jnz _changeDir_22 ; no -->
mov al, byte ptr [ si ] ; get drive letter
call _lowerCase ; lower case letter
mov dl, al ; to dl
sub dl, 'a' ; drive maps to 0, ...
mov byte ptr [ _disk ][ bp ], dl ; save disk
Int21 SelectDisk ; can we select a drive ?
Int21 CurrentDisk ; get current disk
inc si
inc si ; point [si] past drive
cmp al, byte ptr [ _disk ][ bp ] ; disk changed ?
jz _changeDir_22 ; yes -->
mov dx, offset CmndError_InvalidDrive
call DisplayErrorMessage ; display message
jmp short _changeDir_32
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; change directory
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_changeDir_22:
mov dx, si ; points to change string
Int21 ChangeSubdirectory ; try changing dir
jnc _changeDir_32 ; if invalid
call DisplayError ; if error
_changeDir_32:
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Clear Screen ;
;...............................................................;
_Cls:
call CheckNoArgs ; check for no args
jc _cls_36 ; if error -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; stdout a device or file
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
mov bx, STDOUT
Int21 IoControl, 00h ; is device piped to a file ?
jc _clsScreen ; we'll assume its to screen -->
test dx, 80h ; if bit 7 = 0, handle is a file
jnz _clsScreen ; its a physical device -->
mov dl, 'L'-40h ; to a file we'll pipe a top of forms
Int21 DisplayOutput
jmp short _cls_36
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; see how many lines
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_clsScreen:
call PhysClearScreen
_cls_36:
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Delete filename ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:di Arg Array ;
; ax Number of arguments in array ;
;...............................................................;
_Delete:
Entry
def __argarray, di
def _nfiles, 0000
def _filename
defbytes _expandedname, 128
call CheckOneArg
jnc _Delete_06 ; arguments wrong -->
mov dx, offset CmndError_FileNameMissing
call DisplayErrorMessage
Return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; try to locate file (s)
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_Delete_06:
mov dx, word ptr [ di ] ; point to filename arg
storarg _filename, dx ; save pointer
_Delete_08:
xor cx, cx
getarg dx, _filename ; get filename pointer
Int21 FindFirstFile ; does file exist ?
jc _Delete_36 ; no more -->
mov si, offset [ RxDOS_DTA. findFileName ] ; current name
lea di, offset [ _expandedname ][ bp ]
Int21 GetActualFileName ; expand name
jc _Delete_36 ; can't resolve name -->
inc word ptr [ _nfiles ][ bp ]
lea dx, offset [ _expandedname ][ bp ]
Int21 DeleteFile ; delete file
jmp _Delete_08
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; try to locate file
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_Delete_36:
cmp word ptr [ _nfiles ][ bp ], 0000 ; any files deleted ?
jnz _Delete_42 ; yes -->
mov dx, offset CmndError_NoFilesFound
call DisplayErrorMessage
_Delete_42:
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Disk Select Command ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:di Arg Array ;
; ax Number of arguments in array ;
;...............................................................;
_DiskSelect:
push di
inc di
inc di
call CheckNoArgs ; check for no arguments
jc _diskSelect_32 ; if error -->
pop di
push di ; restore pointer to arg 0
mov si, word ptr ss:[ di ] ; pointer to lead argument
cmp byte ptr [ si+1 ], ':' ; drive ?
jnz _diskSelect_32 ; no -->
mov al, byte ptr [ si ] ; get drive letter
call _lowerCase ; lower case letter
mov dl, al ; to dl
sub dl, 'a' ; drive maps to 0, ...
mov byte ptr [ _disk ][ bp ], dl ; save disk
Int21 SelectDisk ; can we select a drive ?
Int21 CurrentDisk ; get current disk
inc si
inc si ; point [si] past drive
cmp al, byte ptr [ _disk ][ bp ] ; disk changed ?
jz _diskSelect_32 ; yes -->
mov dx, offset CmndError_InvalidDrive
call DisplayErrorMessage ; display message
_diskSelect_32:
pop di
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Echo ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:di Arg Array ;
; ax Number of arguments in array ;
;...............................................................;
_Echo:
Entry
ddef __argarray, ss, di
def _args, ax
or ax, ax ; no arguments ?
jz _echo_printcurrent ; none, print current status -->
dec ax ; just one argument ?
jnz _echo_printline ; no, print line -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; test for On/ Off
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
mov si, word ptr [ di ] ; get single argument
mov di, offset RxDOS_OnOff
call CmndLookup ; lookup command
jc _echo_printline ; if not on/off, print line -->
mov byte ptr [ _EchoStatus ], bl ; set echo status
Return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; print current line
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_echo_printline:
mov di, word ptr [ __argarray. _pointer ][ bp ]
mov dx, word ptr [ di ] ; get start of string
call DisplayLine
call CRLF
Return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; print on/off value
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_echo_printcurrent:
mov bl, byte ptr [ _EchoStatus ]
xor bh, bh
add bx, bx
mov dx, word ptr [ _EchoOptions ][ bx ]
call DisplayLine
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; End Call ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:di Arg Array ;
; ax Number of arguments in array ;
;...............................................................;
_EndCall:
mov bx, word ptr [ RxDOS_BatchFile. batchFileHandle ]
Int21 CloseFile ; close file
mov word ptr [ RxDOS_BatchFile. batchFileHandle ], 0000
cmp word ptr [ RxDOS_StackFrameNumEntries ], 0000
jz _endcall_18 ; if no more files to backup to -->
dec word ptr [ RxDOS_StackFrameNumEntries ]
add word ptr [ RxDOS_PrevStackFrame ], sizeBATCH_ARGS
mov si, word ptr [ RxDOS_PrevStackFrame ]
mov di, offset RxDOS_BatchFile
mov cx, sizeBATCH_ARGS
rep movsb ; copy current args to save area
mov si, word ptr [ RxDOS_PrevStackFrame ]
cmp word ptr [ RxDOS_StackFrameNumEntries ], 0000
jnz _endcall_18 ; if more files to backup to -->
mov byte ptr [ _EchoStatus ], Yes
_endcall_18:
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Execute Program or Batch File ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:di Arg Array ;
; ax Number of arguments in array ;
;...............................................................;
_executeProgram:
; eventually, check for .exe and .com, of course
call _Call
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Goto Label ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; if batch file, locate label ;
;...............................................................;
_Goto:
Entry
def _labelPtr, si
ddef _filePosition
defbytes _buffer, sizeCmdLineStruct
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; prep argument
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_goto_06:
cmp byte ptr [ si ], ':'
jnz _goto_08
inc si
jmp _goto_06
_goto_08:
storarg _labelPtr, si
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; running batch file ?
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cmp word ptr [ RxDOS_BatchFile. batchFileHandle ], 0000
jz _Goto_36 ; if not running a batch file -->
call CheckOneArg ; must have an arg
jc _Goto_36 ; error -->
call getBatchPosition ; save current batch file position
mov word ptr [ _filePosition. _low ][ bp ], ax
mov word ptr [ _filePosition. _high ][ bp ], dx
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; read lines
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
xor cx, cx
xor dx, dx
mov bx, word ptr [ RxDOS_BatchFile. batchFileHandle ]
Int21 MoveFilePointer, SEEK_BEG ; start at beg of file
_goto_16:
xor ax, ax ; no echo searching lines
mov bx, word ptr [ RxDOS_BatchFile. batchFileHandle ]
lea si, offset [ _buffer ][ bp ]
mov byte ptr [ bufMaxLength ][ si ], sizeCmdLine
call _ReadBatch ; read batch line
jz _goto_32 ; set position -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; compare against search argument
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
xor bh, bh
mov bl, byte ptr [ _buffer. bufActualLength ][ bp ]
lea di, offset [ _buffer. bufData ][ bp ]
mov byte ptr [ di + bx ], 00
mov si, word ptr [ _labelPtr ][ bp ]
_goto_18:
cmp byte ptr [ di ], ' '
jz _goto_22
cmp byte ptr [ di ], ':'
jnz _goto_26
_goto_22:
inc di
jmp _goto_18
_goto_26:
call _compareSubString ; label located ?
jnz _goto_16 ; no -->
jmp short _goto_36 ; line located !
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; can't find, reset line location
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_goto_32:
mov dx, word ptr [ _filePosition. _low ][ bp ]
mov cx, word ptr [ _filePosition. _high ][ bp ]
mov bx, word ptr [ RxDOS_BatchFile. batchFileHandle ]
Int21 MoveFilePointer, SEEK_BEG ; restore pointer
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_goto_36:
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; If [not] ERRORLEVEL number command ;
; If [not] EXIST filename command ;
; If [not] string1==string2 command ;
;...............................................................;
_If:
Entry
def __argarray, di
defwords _args, 20 ; stores up to 10 arg entries
def _notflag, 0000
def _returnvalue
def _usedportion, 0000
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; type first few arguments
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
mov cx, 5 ; # args to scan
lea di, offset [ _args ][ bp ] ; pointer to arg store value
push cx
push di
xor ax, ax
add cx, cx ; # ddef entries to clear
rep stosw
pop bx
pop cx
mov di, word ptr [ __argarray ][ bp ]
_If_08:
mov si, word ptr [ di ] ; get argument passed
or si, si ; no more args ?
jz _If_16 ; quit typing -->
mov word ptr [ bx. _argtext ], si ; pointer to text
push di
push bx
push cx
mov di, offset RxDOS_IfOptions
call CmndLookup ; lookup command
mov ax, bx ; save type
pop cx
pop bx
pop di
jc _If_12
mov word ptr [ bx. _argtype ], ax ; value returned from lookup
_If_12:
add bx, 4 ; lookup first three args
add di, 2 ; lookup first three args
loop _If_08
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; see if == special case
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_If_16:
lea bx, offset [ _args ][ bp ] ; pointer to arg
cmp word ptr [ bx. _argtype ], IF_NOT ; not argument ?
jnz _If_20 ; no -->
add bx, 4 ; then we'll use next as base
storarg _notflag, -1 ; if not
_If_20:
cmp word ptr [ bx. _argtype ], IF_ERRORLEVEL
ifz _ifErrorLevel
cmp word ptr [ bx. _argtype ], IF_EXIST
ifz _ifExist
mov si, word ptr [ bx + 4 ][ _argtext ] ; next arg
or si, si ; no text ?
jz _IfSyntaxError ; syntax error -->
cmp word ptr [ si ], "==" ; equals case ?
jz _ifEquals
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; syntax error
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_IfSyntaxError:
mov dx, offset CmndError_SyntaxError
call DisplayErrorMessage ; display message
Return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; if equals
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_ifEquals:
mov si, word ptr [ bx ][ _argtext ]
or si, si ; arg before =='s
jz _IfSyntaxError ; if syntax error -->
mov di, word ptr [ bx + 12][ _argtext ]
or di, di ; arg after =='s
jz _IfSyntaxError ; if syntax error -->
storarg _usedportion, di
_ifEquals_04:
cmpsb ; compare equals ?
jnz _ifEquals_08 ; not equal -->
mov al, byte ptr [ di ]
cmp al, '=' ; at end of arg ?
jz _ifEquals_04
cmp al, ' ' ; at end of arg ?
jnz _ifEquals_04
_ifEquals_08:
lahf ; zer/not zero to ah
xor ah, byte ptr [ _notflag ][ bp ] ; toggle Not Equal Bit
and ah, 01000000b ; not zero if logical continue
jnz _ifTrue
Return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; if errorlevel
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_ifErrorLevel:
Int21 GetReturnCode ; get return value
and ax, 255 ; get previous return value
storarg _returnvalue, ax
mov si, word ptr [ bx + 4 ][ _argtext ] ; get text pointer to next arg
storarg _usedportion, si
or si, si
jz _IfSyntaxError ; if syntax error -->
call _GetNumber ; get expected number
jc _IfSyntaxError ; if syntax error -->
cmp ax, word ptr [ _returnvalue ][ bp ] ; current >= return value ?
lahf ; zer/not zero to ah
xor ah, byte ptr [ _notflag ][ bp ] ; toggle Not Equal Bit
and ah, 00000001b ; not zero if logical continue
jz _ifTrue ; do rest of line -->
Return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; if exist
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_ifExist:
mov cx, ATTR_DIRECTORY
mov dx, word ptr [ bx + 4 ][ _argtext ] ; get text pointer to next arg
storarg _usedportion, dx
Int21 FindFirstFile ; does this file exist ?
lahf ; zer/not zero to ah
xor ah, byte ptr [ _notflag ][ bp ] ; toggle Not Equal Bit
and ah, 00000001b ; not zero means not True
jz _ifTrue ; do rest of line -->
Return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; if cond is true. execute command that follows
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_ifTrue:
getarg di, __argarray
getarg dx, _usedportion ; used args
sub di, 2
_ifTrue_08:
inc di
inc di
cmp word ptr [ di ], 0000
ifz _IfSyntaxError
cmp word ptr [ di ], dx ; located used part of If ?
jc _ifTrue_08 ; not yet -->
inc di
inc di
call _executeCommandArray
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Make Directory ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:di Arg Array ;
; ax Number of arguments in array ;
;...............................................................;
_makeDir:
call CheckOneArg ; see if 1 arg
jc _makeDir_32 ; if error -->
_makeDir_22:
mov dx, word ptr [ di ] ; point to filename arg
Int21 CreateSubdirectory ; try changing dir
jnc _makeDir_32 ; if valid -->
cmp ax, errAccessDenied ; access denined ?
jnz _makeDir_26 ; show other errors -->
mov dx, offset CmndError_SubDirAlreadyExists
call DisplayErrorMessage
jmp short _makeDir_32
_makeDir_26:
call DisplayError ; if error
_makeDir_32:
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Path ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:di Arg Array ;
; ax Number of arguments in array ;
;...............................................................;
_Path:
Entry
def __argarray, di
def _newPathArg
def _pathArgBeg
def _pathEndPtr, 0000
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; bypass initial = sign
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_Path_04:
mov si, word ptr [ di ]
or si, si
jz _Path_06
cmp byte ptr [ si ], '='
jnz _Path_06
inc di
inc di
jmp _Path_04
_Path_06:
storarg _newPathArg, si
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; locate current path arg, if any.
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
mov si, offset RxDOS_PathSpec ; locate PATH=
call searchEnvVariable ; env variable located ?
jz _Path_08 ; if arg located -->
storarg _pathEndPtr, di ; else this points to end
xor di, di ; say not found
_Path_08:
storarg _pathArgBeg, di
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; if no command given, type out current path value
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
getarg si, _newPathArg
or si, si ; no args passed ?
jnz _Path_16 ; yes, go update path -->
getarg dx, _pathArgBeg
or dx, dx ; if arg passed ,
jz _Path_14 ; else, display NoPath
push es
mov es, word ptr [ _EnvSegment ]
call DisplayLine ; show current path
call CRLF ; cr/lf
pop es
Return
_Path_14:
mov dx, offset CmndError_NoPath
call DisplayLine ; show current path
Return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; else, set path
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_Path_16:
push si ; env string to add
getarg di, _pathEndPtr ; get pointer to end
getarg dx, _pathArgBeg ; restore arg to path
or dx, dx ; was any found ?
jz _Path_24 ; no, no need to delete -->
mov di, dx
call deleteEnvVariable
_Path_24:
mov si, offset RxDOS_PathSpec ; locate PATH=
call insertEnvVariable
dec di
pop si
call insertEnvVariable
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Pause ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:di Arg Array ;
; ax Number of arguments in array ;
;...............................................................;
_Pause:
mov dx, offset _PressAnyKeyToContinue
Int21 PrintString
Int21 ClearBufferedKeyboardInput, KeyboardInput
call CRLF
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Remark (Rem ) ;
;...............................................................;
_Rem:
ret ; do nothing
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Remove Directory ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:di Arg Array ;
; ax Number of arguments in array ;
;...............................................................;
_RemDir:
call CheckOneArg ; see if 1 arg
jc _removeDir_32 ; if error -->
mov dx, word ptr [ di ] ; point to filename arg
Int21 RemoveSubdirectory ; try command
jnc _removeDir_32 ; if valid -->
call DisplayError ; if error
_removeDir_32:
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; SET ;
; SET variable= ;
; SET variable=string ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Display, set or remove environment variable. ;
;...............................................................;
_Set:
Entry
def __argarray, di
call CountArgs
or ax, ax ; if no args
jnz _SetEnvVariable ; set/ clear env variable -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; display environment variables
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_SetDisplay:
xor si, si
mov es, word ptr [ _EnvSegment ]
_SetDisplay_08:
cmp byte ptr es:[ si ], 00
jz _SetDisplayReturn
cmp byte ptr es:[ si ], ';' ; if comment,
jz _SetDisplay_12 ; skip -->
mov dx, si
call DisplayLine
call CRLF
_SetDisplay_12:
inc si ; scan to end of env string
cmp byte ptr es:[ si - 1 ], 00
jnz _SetDisplay_12
jmp _SetDisplay_08
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; set/clear environment variable
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_SetEnvVariable:
mov di, word ptr [ __argarray ][ bp ]
mov si, word ptr [ di ] ; get lead arg
_SetEnvVariable_08:
inc si
cmp byte ptr [ si-1 ], '=' ; line contains a break ?
jz _SetEnvVariable_12 ; yes -->
cmp byte ptr [ si-1 ], 00 ; end of string ?
jnz _SetEnvVariable_08 ; not yet -->
mov dx, offset CmndError_SyntaxError
call DisplayErrorMessage ; display message
Return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; upper case up to '='
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_SetEnvVariable_12:
mov si, word ptr [ di ] ; get lead arg
_SetEnvVariable_14:
mov al, byte ptr [ si ]
or al, al
jz _SetEnvVariable_16
cmp al, '='
jz _SetEnvVariable_16
call _upperCase
mov byte ptr [ si ], al
inc si
jmp _SetEnvVariable_14
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; search/ delete
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_SetEnvVariable_16:
mov si, word ptr [ di ] ; get lead arg
call searchEnvVariable ; env variable located ?
jnz _SetEnvVariable_18 ; not found -->
call deleteEnvVariable ; delete env variable
_SetEnvVariable_18:
mov si, word ptr [ __argarray ][ bp ]
mov si, word ptr [ si ] ; get lead arg
call insertEnvVariable ; insert at end
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_SetDisplayReturn:
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Shift ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; No parameters expected ;
;...............................................................;
_Shift:
mov si, offset ( RxDOS_BatchFile. batchArgPtrs ); copy args down
mov cx, word ptr [ RxDOS_BatchFile. batchNumArgs ]
or cx, cx
jz _shift_32 ; if no arguments -->
_shift_08:
mov ax, word ptr [ si + 2 ]
mov word ptr [ si ], ax ; shift arg down
add si, 2 ; point to next arg
loop _shift_08 ; loop through all args
dec word ptr [ RxDOS_BatchFile. batchNumArgs ] ; decr # args
_shift_32:
mov word ptr [ si ], 0000 ; null out last arg
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Truename [ anypath ] ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Displays the DOS expanded filename. ;
; ;
;...............................................................;
_Truename:
Entry
defbytes _buffer, 128
call CheckOptOneArg ; should have an arg
jc _truename_36 ; error -->
mov si, word ptr [ di ] ; get argument passed
lea di, offset [ _buffer ][ bp ]
Int21 GetActualFileName
lea dx, offset [ _buffer ][ bp ]
call DisplayLine ; print line
_truename_36:
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Type filename ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Unlike MSDOS, TYPE will permit both the use of the pause /p ;
; switch and wild card characters in a name. ;
; ;
;...............................................................;
_Type:
Entry
def __argarray, di
def _handle
defbytes _buffer, 130
mov cx, 0001 ; at least one arg
mov dx, 0999 ; unlimitd number of args
mov bx, offset _TypeSwitches
call PreProcessCmndLine ; process switches
jc _TypeReturn ; if error -->
mov ax, word ptr [ _TypePauseSwitch. swFlags ]
call setPagingMode
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; get next argument
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_TypeNext:
mov di, word ptr [ __argarray ][ bp ]
add word ptr [ __argarray ][ bp ], 2
mov dx, word ptr [ di ]
or dx, dx ; any more args ?
jz _TypeReturn ; if no more -->
xor cx, cx
Int21 findFirstFile ; filename found for arg ?
jnc _TypeOpenFile ; no, go to next -->
push dx
mov dx, offset _TypeCannotFind
call DisplayLine
pop dx
call DisplayLine ; show arg
jmp _TypeNext
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; open and print
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_TypeOpenFile:
mov dx, offset [ RxDOS_DTA. findFileName ]
Int21 OpenFile, 0000 ; open
storarg _handle, ax
jc _TypeNext
call CRLF
mov dx, offset [ RxDOS_DTA. findFileName ]
call DisplayLine ; show arg
call CRLF
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; read and list
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_TypeReadFile:
mov cx, 128 ; how much to read
getarg bx, _handle ; get handle
lea dx, offset [ _buffer ][ bp ] ; where to read
Int21 ReadFile ; read buffer
jc _TypeCloseFile
or ax, ax ; at end of file ?
jz _TypeCloseFile ; yes, go to next -->
mov cx, ax ; how much read
lea dx, offset [ _buffer ][ bp ] ; where to read
call DisplayLineCount
jmp _TypeReadFile
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; close file
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_TypeCloseFile:
getarg bx, _handle ; get handle
Int21 CloseFile
call CRLF
Int21 findNextFile ; more files ?
jnc _TypeOpenFile ; yes, open file -->
jmp _TypeNext ; else go to next -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_TypeReturn:
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Verify [ ON | OFF ] ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Sets, clears or reports on RxDOS disk verify parameters. ;
; ;
;...............................................................;
_Verify:
Entry
ddef __argarray, ss, di
def _args, ax
call CheckOptOneArg ; see if 1 arg
jc _VerifyExit ; if error -->
or ax, ax ; any arguments ?
jz _VerifyPrintcurrent ; none, print current status -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; test for On/ Off
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
mov si, word ptr [ di ] ; get single argument
mov di, offset RxDOS_OnOff
call CmndLookup ; lookup command
jc _VerifyError ; if not on/off, print line -->
mov al, bl
Int21 SetVerifySwitch ; set or clear verify switch
Return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; must specify on or off
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_VerifyError:
mov dx, offset CmndError_MustSpecifyOnOff
call DisplayErrorMessage
Return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; print verify on/off value
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_VerifyPrintcurrent:
Int21 GetVerify
mov bl, al
xor bh, bh
add bx, bx
mov dx, word ptr [ _VerifyOptions ][ bx ]
call DisplayLine
_VerifyExit:
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Version ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; No parameters expected ;
;...............................................................;
_Ver:
call CheckNoArgs ; check for no arguments
jc _ver_32 ; if error -->
call CRLF
mov dx, offset RxDOS_Version
call DisplayLine
mov dx, offset RxDOS_VersionCopyright
call DisplayLine
_ver_32:
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Volume ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Displays Volume Information ;
; ;
;...............................................................;
_Vol:
Entry
def _currdisk, 0000
defbytes _printbuffer, 128
Int21 CurrentDisk
add al, 'A' ; get drive
mov byte ptr [ _currdisk ][ bp ], al ; save current disk
call checkOptOneArg
jc _Vol_60 ; parameter is wrong -->
jz _Vol_30 ; if no parameters -->
mov si, word ptr [ di ] ; get pointer to first arg
mov ax, word ptr [ si ]
cmp ah, ':' ; not a drive specification ?
jnz _Vol_62 ; no -->
call _lowerCase ; disk id
and ax, not 20h ; upper case
cmp al, 'Z'+1
jnc _Vol_62
cmp al, 'A'
jc _Vol_62
storarg _currdisk, ax ; save disk
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; get disk volume
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_Vol_30:
mov bx, offset _Dir_NoVolumeLabel ; assume no volume label
call returnVolumeName
jc _Vol_62 ; cannot open drive -->
jnz _Vol_34 ; if no volume name -->
push di ; save vol label pointer
mov bx, offset _Dir_VolumeLabel ; print statement format
_Vol_34:
lea di, offset [ _currdisk ][ bp ] ; pointer to current disk
push di ; current disk
push bx ; format
lea di, offset [ _printbuffer ][ bp ]
push di
call _sprintf
add sp, ax ; # args passed
call DisplayLine
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_Vol_60:
Return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; drive specification error
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_Vol_62:
mov dx, offset CmndError_InvalidDrive
call DisplayErrorMessage
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Commands Not Supported ;
;...............................................................;
_Chcp:
_Ctty:
_Loadhigh:
mov dx, offset CmndError_NotSupportedInRxDOS
call DisplayErrorMessage
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Other Commands ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; ;
; ;
;...............................................................;
_Help:
_History:
_Move:
mov dx, offset CmndError_NotSupportedYet
call DisplayErrorMessage
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Not A Valid Command ;
;...............................................................;
_NotValidCommand:
mov dx, offset CmndError_BadCommandOrFileName
call DisplayErrorMessage
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Exit (;** just a debug backdoor so far) ;
;...............................................................;
_Exit:
int 3
Int21 TerminateProgram, 00h
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Save Batch File Position ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Returns: ;
; bx batch file handle ;
; dx:ax position in batch file ;
;...............................................................;
getBatchPosition:
xor cx, cx
xor dx, dx
mov bx, word ptr [ RxDOS_BatchFile. batchFileHandle ]
Int21 MoveFilePointer, SEEK_CUR
ret
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Manage Stdin Input ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:dx buffer (pointer to max length) ;
;...............................................................;
_getStdinLine:
Entry
def _buffer, dx
push di
push bx
push dx
mov di, dx
mov byte ptr [ bufActualLength ][ di ], 00
mov bx, STDIN
Int21 IoControl, 00h ; get stdin device data
test dx, 80h ; file or device ?
jnz _getStdinLine_32 ; device, just read directly -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; read by character if file
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_getStdinLine_08:
mov di, word ptr [ _buffer ][ bp ]
mov bl, byte ptr [ bufActualLength ][ di ] ; store character into buffer
xor bh, bh
lea dx, offset [ bufData ][ di + bx ] ; data address
mov cx, 1
mov bx, STDIN
Int21 ReadFile ; read character
jc _getStdinLine_28
or ax, ax ; read anything ?
jz _getStdinLine_28 ; no, see if return -->
mov di, word ptr [ _buffer ][ bp ]
mov bl, byte ptr [ bufActualLength ][ di ] ; store character into buffer
xor bh, bh
mov dl, byte ptr [ bufData ][ di + bx ] ; get character
cmp dl, 'J'-40h ; character lf ?
jz _getStdinLine_08 ; ignore lf -->
push dx
Int21 DisplayOutput ; echo character
pop dx
inc byte ptr [ bufActualLength ][ di ] ; store character into buffer
cmp dl, 'M'-40h ; character cr ?
jz _getStdinLine_34 ; yes, end of input -->
mov al, byte ptr [ bufActualLength ][ di ] ; actual less than max ?
cmp al, byte ptr [ bufMaxLength ][ di ] ; get max
jc _getStdinLine_08
jmp short _getStdinLine_34
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; end of file
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_getStdinLine_28:
mov di, word ptr [ _buffer ][ bp ]
mov dl, byte ptr [ bufActualLength ][ di ] ; store character into buffer
or dl, dl ; any characters ?
jnz _getStdinLine_34 ; yes, return -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; cancel stdin
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
mov ax, 1 ; this may have to change !
mov bx, STDIN
call _CloseRedirectedDevice
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; read directly if device
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_getStdinLine_32:
pop dx ; buffer address
Int21 GetLine ; read direct from device
_getStdinLine_34:
getarg dx, _buffer
pop bx
pop di
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Read Line ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:si buffer (pointer to max length) ;
; bx file handle (null value means stdin ) ;
; al echo status ;
;...............................................................;
_ReadLine:
Entry
def _Handle, bx
ddef _buffer, ss, si
or bx, bx ; process from batch file ?
jz _ReadLine_08 ; no, read from console -->
call _ReadBatch ; else read batch file
jmp short _ReadLine_26
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; read from keyboard
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_ReadLine_08:
call DisplayPrompt ; display prompt
mov dx, word ptr [ _buffer. _pointer ][ bp ]
call _getStdinLine ; read buffer
call CRLF
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_ReadLine_26:
mov si, word ptr [ _buffer. _pointer ][ bp ]
mov al, byte ptr [ bufActualLength ][ si ]
and ax, 255 ; actual length
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Read Batch Line ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Usage: ;
; ss:si buffer (pointer to max length) ;
; bx file handle (null value means stdin ) ;
; al echo status ;
;...............................................................;
_ReadBatch:
Entry
def _bytesRead
def _echoline, ax
def _Handle, bx
ddef _buffer, ss, si
add si, bufData ; offset to data
ddef _bufferData, ss, si
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; read line
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
mov cx, sizeCmdLine
mov dx, word ptr [ _bufferData. _pointer ][ bp ]; where to read
mov bx, word ptr [ RxDOS_BatchFile. batchFileHandle ]
call ReadBatchLine
mov word ptr [ _bytesRead ][ bp ], ax
jnz _ReadBatch_08 ; no -->
call _EndCall ; end batch file call
xor ax, ax ; return zero bytes
mov di, word ptr [ _buffer. _pointer ][ bp ] ; buffer address
mov byte ptr [ bufActualLength ][ di ], al
Return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; trim line to carriage return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_ReadBatch_08:
mov di, word ptr [ _buffer. _pointer ][ bp ] ; buffer address
mov byte ptr [ bufActualLength ][ di ], al
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; perform variable replacement
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_ReadBatch_20:
mov bx, word ptr [ _bytesRead ][ bp ]
mov si, word ptr [ _bufferData. _pointer ][ bp ]; buffer address
mov byte ptr [ si+bx ], 00
call ReplaceTempVariables ; replace %n variables
mov si, word ptr [ _buffer. _pointer ][ bp ] ; buffer address
mov byte ptr [ bufActualLength ][ si ], cl
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; echo enabled ?
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cmp byte ptr [ _echoLine ][ bp ], 00
jz _ReadBatch_32 ; echo is off -->
mov cx, ax ; length of line
mov di, word ptr [ _bufferData. _pointer ][ bp ]; buffer address
_ReadBatch_24:
cmp byte ptr [ di ], '@' ; line starts with @ ?
jz _ReadBatch_32 ; yes, no echo -->
cmp byte ptr [ di ], ' ' ; still in white space ?
jnz _ReadBatch_26 ; no, echo line -->
inc di
loop _ReadBatch_24
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; echo this line
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_ReadBatch_26:
call DisplayPrompt ; display prompt
mov dx, di
call DisplayLine ; echo line
call CRLF
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_ReadBatch_32:
mov di, word ptr [ _buffer. _pointer ][ bp ] ; buffer address
mov ax, word ptr [ _bytesRead ][ bp ]
or di, di ; data always returned
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Read Batch Line ;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
; ;
; Returns: ;
; bx batch file handle ;
; dx line buffer address ;
;...............................................................;
ReadBatchLine:
Entry
def _Handle, bx
def _lineBuffer, dx
def _bytesRead, 0000
ddef _filePosition
defbytes _tempbuffer, 2
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; get current position in file
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
xor cx, cx
xor dx, dx
Int21 MoveFilePointer, SEEK_CUR
mov word ptr [ _FilePosition. _low ][ bp ], ax
mov word ptr [ _FilePosition. _high ][ bp ], dx ; save current position
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; get current position in file
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
getarg si, _lineBuffer
mov byte ptr [ si ], 00 ; set null terminator at beg
getarg bx, _Handle
mov cx, sizeCmdLine
getarg dx, _lineBuffer ; where to read batch file
Int21 ReadFile ; read
jc ReadBatchLine_36 ; if error -->
mov word ptr [ _bytesRead ][ bp ], ax
or ax, ax ; end of batch file ?
jz ReadBatchLine_36 ; yes -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; trim line to carriage return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
mov cx, ax ; scan line
getarg di, _lineBuffer ; where to read batch file
mov al, 'M'-40h
repnz scasb ; scan for cr
jz ReadBatchLine_20 ; carriage return found -->
ReadBatchLine_12:
mov cx, 1
lea dx, offset [ _tempbuffer ][ bp ] ; scan char by character till cr
Int21 ReadFile ; read
jc ReadBatchLine_36 ; if error -->
or ax, ax ; end of file ?
jz ReadBatchLine_36 ; yes -->
cmp byte ptr [ _tempbuffer ][ bp ], 'M'- 40h ; carriage return ?
jnz ReadBatchLine_12 ; no -->
jmp short ReadBatchLine_30 ; process line a bit -->
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; position line immediately after cr
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ReadBatchLine_20:
mov ax, word ptr [ _bytesRead ][ bp ]
sub ax, cx
push ax
cmp byte ptr [ di ], 'J'-40h
jnz ReadBatchLine_22 ; if line feed doesn't follow -->
inc ax ; account for lf
ReadBatchLine_22:
mov dx, word ptr [ _FilePosition. _low ][ bp ]
mov cx, word ptr [ _FilePosition. _high ][ bp ] ; orig position
add dx, ax
adc cx, 0000
getarg bx, _Handle
Int21 MoveFilePointer, SEEK_BEG ; get current position
pop ax
dec ax ; don't include cr
mov word ptr [ _bytesRead ][ bp ], ax ; bytes read
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; does line begin with a line feed ?
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ReadBatchLine_30:
getarg di, _lineBuffer
cmp byte ptr [ di ], 'J'-40h
jnz ReadBatchLine_32 ; no -->
getarg cx, _bytesRead
mov si, di
inc si
rep movsb ; delete
dec word ptr [ _bytesRead ][ bp ]
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; place null terminator at end
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ReadBatchLine_32:
getarg bx, _bytesRead
getarg si, _lineBuffer
mov byte ptr [ si+bx ], 00 ; set null terminator at end
mov ax, bx
or si, si ; nz means valid return
Return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; end of file or error
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ReadBatchLine_36:
xor ax, ax
Return
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Command Shell Start ;
;...............................................................;
CommandBegin:
cli
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, offset RxDOS_CmdStack
sti
cld
mov byte ptr [ _EchoStatus ], TRUE ; echo is ON
mov word ptr [ RxDOS_BatchFile. batchNumArgs ], 0000 ; no args
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; initialize stack frame
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Entry
defbytes _cmdline, sizeCmdLineStruct
defbytes _SaveBatchInfo, sizeBATCH_ARGS ; previous batch file
mov word ptr [ RxDOS_PrevStackFrame ], sp ; current stack frame
mov si, offset RxDOS_BatchFile
mov di, word ptr [ RxDOS_PrevStackFrame ]
mov cx, sizeBATCH_ARGS
rep movsb ; copy current args to save area
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; get env, psp addresses
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Int21 GetPSPAddress
mov word ptr [ _PSPSegment ], bx
mov es, bx ; set PSP address
mov bx, word ptr es:[ pspEnvironment ] ; get seg of Environment
mov word ptr [ _EnvSegment ], bx
dec bx ; locate Mem Control Block
mov es, bx ; point to mem block
mov bx, word ptr es:[ _memAlloc ] ; allocation in paras of env block
shl bx, 1
shl bx, 1
shl bx, 1
shl bx, 1 ; conv paras to segs
mov word ptr [ _EnvSize ], bx ; save env size
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; set DTA
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Int21 GetDTA
mov word ptr [ RxDOS_OrigDTA. _segment ], es
mov word ptr [ RxDOS_OrigDTA. _pointer ], bx
currSegment es
mov dx, offset RxDOS_DTA
Int21 SetDTA ; set new disk transfer address
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; init screen
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
call PhysClearScreen ; start with a clear screen
mov dx, offset RxDOS_Version
call DisplayLine ; print startup version
mov dx, offset RxDOS_VersionCopyright
call DisplayLine ; print startup version
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; basic command loop
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CommandInput:
mov sp, word ptr [ RxDOS_PrevStackFrame ] ; current stack frame
lea si, offset [ _cmdline ][ bp ]
mov byte ptr ss:[ si ], sizeCmdLine
mov bx, word ptr [ RxDOS_BatchFile. batchFileHandle ]
mov al, byte ptr [ _EchoStatus ]
call _ReadLine
jz CommandInput ; no, redisplay prompt -->
mov bx, ax
lea si, offset [ _cmdline. bufActualLength ][ bp ]
mov byte ptr ss:[ si + bx + 1 ], 00 ; null terminate string
Int2E
jmp CommandInput
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Internal Commands ;
;...............................................................;
Even
RxDOS_InternalCommands:
Cmnd _ChangeDir, 'cd' ;
Cmnd _ChangeDir, 'chdir' ;
Cmnd _MakeDir, 'md' ;
Cmnd _MakeDir, 'mkdir' ;
Cmnd _RemDir, 'rd' ;
Cmnd _RemDir, 'rmdir' ;
Cmnd _Break, 'break' ;
Cmnd _Call, 'call' ;
Cmnd _Chcp, 'chcp' ;
Cmnd _Cls, 'cls' ;
Cmnd _Copy, 'copy' ; *
Cmnd _Ctty, 'ctty' ;
Cmnd _Date, 'date' ;
Cmnd _Delete, 'del' ;
Cmnd _Dir, 'dir' ;
Cmnd _Echo, 'echo' ;
Cmnd _Delete, 'erase' ;
Cmnd _Exit, 'exit' ; *
Cmnd _For, 'for' ;
Cmnd _Goto, 'goto' ;
Cmnd _Help, 'help' ; *
Cmnd _History, 'history' ; * future feature
Cmnd _History, 'his' ; * future feature
Cmnd _If, 'if' ;
Cmnd _Loadhigh, 'lh' ;
Cmnd _Loadhigh, 'loadhigh' ;
Cmnd _Move, 'move' ; * future feature
Cmnd _Path, 'path' ;
Cmnd _Pause, 'pause' ;
Cmnd _Prompt, 'prompt' ;
Cmnd _Rem, 'rem' ;
Cmnd _Rename, 'rename' ; *
Cmnd _Rename, 'ren' ; *
Cmnd _Set, 'set' ;
Cmnd _Shift, 'shift' ;
Cmnd _Time, 'time' ;
Cmnd _Truename, 'truename' ;
Cmnd _Type, 'type' ;
Cmnd _Verify, 'verify' ;
Cmnd _Ver, 'ver' ;
Cmnd _Vol, 'vol' ;
dw -1
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Environment Variables ;
;...............................................................;
RxDOS_CommandSpec: asciz 'COMSPEC='
RxDOS_DirSpec: asciz 'DIRCMD='
RxDOS_PathSpec: asciz 'PATH='
RxDOS_PromptSpec: asciz 'PROMPT='
RxDOS_RxDOSSpec: asciz 'RXDOS='
RxDOS_RxDOSSwitchSpec: asciz 'SWITCH='
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Execution Order ;
;...............................................................;
RxDOS_ExecOrder: asciz '.com'
asciz '.exe'
asciz '.bat'
dw -1
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; On/Off Options ;
;...............................................................;
RxDOS_OnOff: Cmnd 1, 'on'
Cmnd 0, 'off'
dw -1
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; If Options ;
;...............................................................;
RxDOS_IfOptions: Cmnd IF_ERRORLEVEL, 'errorlevel'
Cmnd IF_EXIST, 'exists'
Cmnd IF_EXIST, 'exist'
Cmnd IF_NOT, 'not'
dw -1
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; For Options ;
;...............................................................;
RxDOS_ForArgs: Cmnd _IN, 'in'
Cmnd _DO, 'do'
dw -1
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Version Prompt ;
;...............................................................;
RxDOS_Version: db 'RxDOS Version 5.00', 0
RxDOS_VersionCopyright: db 13, 10
db '(c) Copyright 1990-1993 Api Software and Michael Podanoffsky', 13, 10
db 'All rights reserved', 13, 10, 13, 10, 0
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Error Table ;
;...............................................................;
Even
CmndError_TextReferenceTable:
dw 0 ; 0000
dw 0 ; 0001
dw CmndError_FileNotFound ; 0002
dw CmndError_InvalidDirectory ; 0003
dw 0 ; 0004
dw CmndError_AccessDenied ; 0005
dw 0 ; 0006
dw 0 ; 0007
dw 0 ; 0008
dw 0 ; 0009
dw 0 ; 0010
dw 0 ; 0011
dw 0 ; 0012
dw 0 ; 0013
dw 0 ; 0014
dw 0 ; 0015
dw CmndError_CurrentDirectory ; 0016
CmndError_RefTableEntries equ ($ - CmndError_TextReferenceTable)/2
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Error Messages ;
;...............................................................;
CmndError_AccessDenied: asciz 'access denied'
CmndError_BadCommandOrFileName: asciz 'bad command or file name could not be found'
CmndError_BadSwitch: asciz 'bad switch - '
CmndError_CannotCopyUntoSelf: asciz 'file cannot be copied unto itself'
CmndError_CannotCreateFile: asciz 'cannot create destination file'
CmndError_ContentsLostBeforeCopy:asciz 'contents of file lost before copy'
CmndError_CurrentDirectory: asciz 'cannot remove current directory'
CmndError_FileAlreadyExists: asciz 'file not found or already exists'
CmndError_FileNotFound: asciz 'file not found'
CmndError_NoFilesFound: asciz ' no files found', 13, 10
CmndError_InvalidDate: asciz 'invalid date'
CmndError_InvalidDirectory: asciz 'invalid directory'
CmndError_InvalidDrive: asciz 'invalid drive'
CmndError_InvalidTime: asciz 'invalid time'
CmndError_MustSpecifyOnOff: asciz 'must specify ON or OFF'
CmndError_NotSupportedYet: asciz 'command not supported yet !'
CmndError_NotSupportedInRxDOS: asciz 'command not supported in RxDOS'
CmndError_FileNameMissing: asciz 'file name missing'
CmndError_SubDirAlreadyExists: asciz 'subdirectory already exists'
CmndError_SyntaxError: asciz 'syntax error - use Help'
CmndError_TooManyParameters: asciz 'too many parameters - '
CmndError_NoPath: asciz 'no path'
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Other Variables ;
;...............................................................;
RxDOS_NewLine: db 13, 10, 0
db 'c:'
RxDOS_RootDirectory db '\*.*', 0 ; root directory
RxDOS_AllFiles db '*' ; combines to for *.*
RxDOS_AllExtensions db '.*', 0
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Echo/ Paging ;
;...............................................................;
_EchoStatus db TRUE ; echo is ON
PageLines db 00 ; paging mode
LinesDisplayed dw 00 ; # lines displayed, curr page
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Prompt ;
;...............................................................;
RxDOS_DefaultPrompt db '$n$g', 0
RxDOS_Prompt db '$n$g', 0, 128 dup(0)
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Special Command Separators ;
;...............................................................;
_CmndParse_Separators db ' <>|[],+=()%', doubleQuote, singleQuote, 0
_SwitchChar db '/' ; switch character
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Environment Location/ Size ;
;...............................................................;
_PSPSegment dw 0 ; PSP Segment Address
_EnvSegment dw 0 ; Env Segment Address
_EnvSize dw 0 ; Env Size (bytes)
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Switches ;
;...............................................................;
BATCH_ARGS struc
batchArgPtrs dw ? ; 0
dw ? ; 1 arg pointers
dw ? ; 2 .
dw ? ; 3 .
dw ? ; 4 .
dw ? ; 5 .
dw ? ; 6 .
dw ? ; 7 .
dw ? ; 8 .
dw ? ; 9 .
batchNumArgs dw ? ; number of batch arguments
batchFileHandle dw ? ; batch file handle
batchFilePosition dd ? ; batch file position
batchArgStore db 128 dup(0)
BATCH_ARGS ends
sizeBATCH_ARGS equ size BATCH_ARGS
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Batch File Arguments ;
;...............................................................;
RxDOS_BatchFile db sizeBATCH_ARGS dup(0)
RxDOS_PrevStackFrame dw 0 ; end call stack frame
RxDOS_StackFrameNumEntries dw 0 ; number of entries in stack
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Restore Original Parameters ;
;...............................................................;
RxDOS_OrigDTA dd ? ; original DTA value
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Type Switches ;
;...............................................................;
_TypeSwitches:
_TypePauseSwitch: Switch 'p', 0
db -1
_TypeCannotFind: asciz 'cannot find - '
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Dir Switches ;
;...............................................................;
_DirSwitches:
_DirPauseSwitch: Switch 'p', 0
_DirWideSwitch: Switch 'w', 0
_DirAttribSwitch: Switch 'a', SW_LETTERCHOICE, SW_DIR_ATTRIB
_DirOrderSwitch: Switch 'o', SW_LETTERCHOICE, SW_DIR_ORDER
_DirSubDirSwitch: Switch 's', 0
_DirLowerCaseSwitch: Switch 'l', 0
_DirBareSwitch: Switch 'b', 0
db -1
SW_DIR_ATTRIB: db '-dnsra', 0
SW_DIR_ORDER: db '-negsd', 0
_Dir_NoVolumeLabel: asciz ' Volume in drive %c has no label', 13, 10
_Dir_VolumeLabel: asciz ' Volume in drive %c is %s', 13, 10
_Dir_VolumeSerialNumber: asciz ' Volume Serial Number is %s', 13, 10
_Dir_DirectoryOf: asciz ' Directory of %s', 13, 10, 13, 10
_Dir_Files: db ' %5d file(s) %11,ld bytes', 13, 10
db ' %11,ld bytes free', 13, 10, 0
_Dir_FileEntry: db '%8s %3s %9ld %s %s', 13, 10, 0
_Dir_DirEntry: db '%8s %3s <DIR> %s %s', 13, 10, 0
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Copy Messages ;
;...............................................................;
_Copy_FilesCopied: asciz ' %d file(s) copied'
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Pause/ Continue ;
;...............................................................;
_PressAnyKeyToContinue: asciz 'Press any key to continue . . . $'
_Dir_Continuing: asciz '(continuing %s)', 13, 10
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Break Display Options ;
;...............................................................;
_BreakOptions: dw _BreakIsOFF, _BreakIsON
_BreakIsOFF: asciz 'Break is OFF', 13, 10
_BreakIsON: asciz 'Break is ON', 13, 10
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Echo Display Options ;
;...............................................................;
_EchoOptions: dw _EchoIsOFF, _EchoIsON
_EchoIsOFF: asciz 'Echo is OFF', 13, 10
_EchoIsON: asciz 'Echo is ON', 13, 10
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Verify Display Options ;
;...............................................................;
_VerifyOptions: dw _VerifyIsOFF, _VerifyIsON
_VerifyIsOFF: asciz 'Verify is OFF', 13, 10
_VerifyIsON: asciz 'Verify is ON', 13, 10
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Date Display Options ;
;...............................................................;
_ShowCurrentDate: asciz 'Current date is %s'
_PleaseEnterDate: asciz 13, 10, 'Enter new date (mm-dd-yy): '
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Time Display Options ;
;...............................................................;
_ShowCurrentTime: asciz 'Current time is %s'
_PleaseEnterTime: asciz 13, 10, 'Enter new time: '
RxDOSIntl_DateTimeTable: intldate 001, 'mm/dd/yyyy hh:mm:ss.00' ; USA
intldate 002, 'yyyy-mm-dd HH:mm:ss,00' ; Canada-French
intldate 003, 'dd/mm/yyyy hh:mm:ss.00' ; Latin America
intldate 031, 'dd-mm-yyyy HH:mm:ss,00' ; Netherlands
intldate 032, 'dd/mm/yyyy HH:mm:ss,00' ; Belgium
intldate 033, 'dd.mm.yyyy HH:mm:ss,00' ; France
intldate 034, 'dd/mm/yyyy HH:mm:ss,00' ; Spain
intldate 036, 'yyyy-mm-dd HH:mm:ss,00' ; Hungary
intldate 038, 'yyyy-mm-dd HH:mm:ss,00' ; Yugoslavia
intldate 039, 'dd/mm/yyyy HH.mm.ss,00' ; Italy
intldate 041, 'dd.mm.yyyy HH,mm,ss.00' ; Switzerland
intldate 042, 'yyyy-mm-dd HH:mm:ss,00' ; Czechoslovakia
intldate 044, 'dd/mm/yyyy HH:mm:ss.00' ; United Kingdom
intldate 045, 'dd-mm-yyyy HH:mm:ss,00' ; Denmark
intldate 046, 'yyyy-mm-dd HH.mm.ss,00' ; Sweden
intldate 047, 'dd.mm.yyyy HH:mm:ss,00' ; Norway
intldate 048, 'yyyy-mm-dd HH:mm:ss,00' ; Hungary
intldate 049, 'dd.mm.yyyy HH:mm:ss,00' ; Germany
intldate 055, 'dd/mm/yyyy HH:mm:ss,00' ; Brazil
intldate 061, 'dd/mm/yyyy HH:mm:ss.00' ; Intl English
intldate 351, 'dd-mm-yyyy HH:mm:ss,00' ; Portugal
intldate 358, 'dd.mm.yyyy HH.mm.ss,00' ; Finland
dw -1
RxDOSIntl_TimeTemplate db 'hh:mm:ss.00', 0
RxDOSIntl_DateTemplate db 'www mm/dd/yyyy', 0 ; USA
RxDOSIntl_DayOfWeek db 'SunMonTueWedThuFriSat', 0
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Disk Transfer Address ;
;...............................................................;
even
RxDOS_DTA: db 128 dup(' ')
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Command Shell Stack ;
;...............................................................;
even
db 256 dup('RxDOSCMD') ; 2k
RxDOS_CmdStack dw 0
RxDOSCMD ENDS
END CommandBegin